热门IT资讯网

Spring 常用注解解析

发表于:2024-11-30 作者:热门IT资讯网编辑
编辑最后更新 2024年11月30日,1. 常用注解1.1 @Configuration@Configurationpublic class MainConfig {}@Configuration注解表明这个类是一个配置类,该类中应该包含
1. 常用注解

1.1 @Configuration

@Configurationpublic class MainConfig {}

@Configuration注解表明这个类是一个配置类,该类中应该包含如何在Spring应用上下文中创建bean的细节

1.2 @ComponentScan

@Configuration@ComponentScan("per.ym")public class MainConfig {}

@ComponentScan注解用于启用组件扫描,其作用同xml中配置。上述中的配置将会扫描per.ym包下的所有类,若不配置其value值,它会以配置类所在的包作为基础包(base package)来扫描组件。如果你想同时扫描多个包,可以这样配置:

@Configuration@ComponentScan("per.ym, per.mm")public class MainConfig {}

在上面的例子中,所设置的基础包是以String类型表示的。我认为这是可以的,但这种方法是类型不安全(not type-safe)的。如果你重构代码的话,那么所指定的基础包可能就会出现错误了。除了将包设置为简单的String类型之外,@ComponentScan还提供了另外一种方法,那就是将其指定为包中所包含的类或接口:

@Configuration@ComponentScan(basePackageClasses = {MyService.class,  MyDao.class})public class MainConfig {}

你可以考虑在包中创建一个用来进行扫描的空标记接口(marker interface)。通过标记接口的方式,你依然能够保
持对重构友好的接口引用,但是可以避免引用任何实际的应用程序代码

1.3 @Controller, @Service, @ Repository, @Component

这几个自然不用多说,算是见得最多的了,它们锁修饰的类在被spring容器扫描到时会被加入到spring的管理之中。

@Controller对应表现层的Bean

@Service对应的是业务层Bean

@Repository对应数据访问层Bean

@Component,当你不能明确的选择上述3中,就用这个

Spring应用上下文中所有的bean都会给定一个ID,如果没有明确指定,Spring会根据类名为其指定一个ID,也就是将类名的第一个字母变为小写。你也可以这样显示的指定一个ID:

@Component("ymm")public class Person() {}

Spring支持将@Named(Java依赖注入规范中所提供的)作为@Component注解的替代方案。两者之间有一些细微的差异,但是在大多数场景中,它们是可以互相替换的。

1.4 @Bean

@Bean注解会告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文中
的bean。方法体中包含了最终产生bean实例的逻辑。

@Configurationpublic class MainConifg {    @Bean    public BookDao bookDao(){        return new BookDao();    }}

@Bean注解会告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文中
的bean。方法体中包含了最终产生bean实例的逻辑。

默认情况下,bean的ID与带有@Bean注解的方法名是一样的。在上例中,bean的名字将会是bookDao。如果你想为其设置成一个不同的名字的话,那么可以重命名该方法,也可以通过name属性指定一个不同的名字:

@Configurationpublic class MainConifg {    @Bean(" ymBookDao")    public BookDao bookDao(){        return new BookDao();    }}

还可以像这样设置初始化方法和销毁方法:

@Configurationpublic class MainConifg {    @Bean(initMethod = "init", destroyMethod = "destroy")    public BookDao bookDao(){        return new BookDao();    }}

这如同在xml中配置init-method="init" destroy-method="destory"一样

1.5 @Autowired

借助@Autowired注解可以实现spring的自动装配,自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需求的其他bean

@Servicepublic class BookService {    @Autowired(required=false)    private BookDao bookDao;}

你可以把@Autowired标注在属性、构造器、setter方法上。实际上,Setter方法并没有什么特殊之处,@Autowired注解甚至可以用在类的任何方法上。

除了自带的@Autowired,spring还支持Java规范中的@Resource(JSR250)和@Inject(JSR330),它们之间的区别如下:

@Autowired:

a,默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class),如果有且只有一个 bean匹配依赖需求的话,那么这个bean将会被装配进来;如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找applicationContext.getBean("bookDao");

b,@Qualifier("bookDao"):使用@Qualifier明确指定需要装配的组件的id,而不是使用属性名;

c,自动装配默认一定要将属性赋值好,没有就会报错;可以使用@Autowired(required=false);

d,@Primary:让Spring进行自动装配的时候,默认使用首选的bean;也可以使用@Qualifier指定需要装配的bean的名字;

@Resource:

a,和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;

b,不支持@Primary功能;

c,不支持required=false的功能;

@Inject:

a,和@Autowired一样实现自动装配功能;

b,不支持required=false的功能;

一个可能的例子:

@Configuration@ComponentScan("per.ym.service")public class MainConifgOfAutowired {    @Primary    @Bean("bookDao1")    public BookDao bookDao1(){        BookDao bookDao = new BookDao();        bookDao.setLable("1");        return bookDao;    }   @Bean("bookDao2")   public BookDao bookDao2(){     BookDao bookDao = new BookDao();     bookDao.setLable("2");     return bookDao;   }}   @Servicepublic class BookService {    @Qualifier("bookDao1")    @Autowired(required=false)    private BookDao bookDao;    //@Resource(name="bookDao2")    //private BookDao bookDao;    //@Qualifier("bookDao2")    //@Inject    //private BookDao bookDao;}public class BookDao {    private String lable = "0";    public String getLable() {        return lable;    }    public void setLable(String lable) {        this.lable = lable;    }}

1.6 @Import

通过导入的方式实现快速给容器中导入组件,其上可以配置3种类型的值,分别是普通bean,ImportSelector,ImportBeanDefinitionRegistrar。特别的,你可以导入一个被@Configuration注解修饰的bean,这和在一个spring配置文件中使用引入其他配置文件时相似的

@Configuration@Import({MainConfig2.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})public class MainConfig {}

MainConfig2可以是另一个配置类或者普通的bean:

@Configurationpublic class MainConfig2 {    @Bean    public Person person(){        return new Person();    }}

ImportSelector,其selectImports方法返回的数组中应包含要导入容器的bean的全类名

public class MyImportSelector implements ImportSelector {    //返回值,就是到导入到容器中的组件全类名    //AnnotationMetadata:当前标注@Import注解的类的所有注解信息    @Override    public String[] selectImports(AnnotationMetadata importingClassMetadata) {        //方法不要返回null值,否则会有NPE        return new String[]{"per.ym.bean.Car","per.ym.bean.Dog"};    }}

ImportBeanDefinitionRegistrar,调用BeanDefinitionRegistry.registerBeanDefinition手工注册想要添加到容器中的bean

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {    /**     * AnnotationMetadata:当前类的注解信息     * BeanDefinitionRegistry:BeanDefinition注册类;     */    @Override    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {        //指定Bean定义信息        RootBeanDefinition beanDefinition = new RootBeanDefinition(Red.class);        //注册一个Bean,指定bean名        registry.registerBeanDefinition("red", beanDefinition);    }}

1.7 @Conditional

放在类上,当满足条件时,这个类中配置的所有bean注册才能生效

放在方法上,当满足条件时,才向容器中注册当前bean

@Conditional({WindowsCondition.class})@Configurationpublic class MainConfig {    @Conditional(LinuxCondition.class)    @Bean("linus")    public Person person(){        return new Person("linus");    }}/*** ConditionContext:判断条件能使用的上下文(环境)* AnnotatedTypeMetadata:注释信息*///判断是否windows系统public class WindowsCondition implements Condition {    @Override    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {        //1、能获取到ioc使用的beanfactory        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();        //2、获取类加载器        ClassLoader classLoader = context.getClassLoader();        //3、获取到bean定义的注册类        BeanDefinitionRegistry registry = context.getRegistry();        //4、获取当前环境信息        Environment environment = context.getEnvironment();        String property = environment.getProperty("os.name");        if(property.contains("Windows")){            return true;        }        return false;    }}

1.8 @Profile

根据当前环境,动态的激活和切换一系列组件的功能;指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件

加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中

写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效

@PropertySource("classpath:/dbconfig.properties")@Configurationpublic class MainConfigOfProfile implements EmbeddedValueResolverAware{    @Value("${db.user}")    private String user;    private StringValueResolver valueResolver;    private String  driverClass;    @Profile("test")    @Bean("testDataSource")    public DataSource dataSourceTest(@Value("${db.password}")String pwd) throws Exception{        ComboPooledDataSource dataSource = new ComboPooledDataSource();        dataSource.setUser(user);        dataSource.setPassword(pwd);        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");        dataSource.setDriverClass(driverClass);        return dataSource;    }    @Profile("dev")    @Bean("devDataSource")    public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{        ComboPooledDataSource dataSource = new ComboPooledDataSource();        dataSource.setUser(user);        dataSource.setPassword(pwd);        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dev");        dataSource.setDriverClass(driverClass);        return dataSource;    }    @Profile("prod")    @Bean("prodDataSource")    public DataSource dataSourceProd(@Value("${db.password}")String pwd) throws Exception{        ComboPooledDataSource dataSource = new ComboPooledDataSource();        dataSource.setUser(user);        dataSource.setPassword(pwd);        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/prod");        dataSource.setDriverClass(driverClass);        return dataSource;    }    @Override    public void setEmbeddedValueResolver(StringValueResolver resolver) {        this.valueResolver = resolver;        driverClass = valueResolver.resolveStringValue("${db.driverClass}");    }}db.properties:db.user=rootdb.password=123456db.driverClass=com.mysql.jdbc.Driver

启动命令行中设置环境参数:

-Dspring.profiles.active=test

代码方式设置:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);applicationContext.getEnvironment().setActiveProfiles("dev");
0