spring常用注解

@[toc]

1.常用注解及作用

1.1 @Configuration

声明当前类是一个配置类(相当于一个Spring配置的xml文件)

1.2 @ComponentScan

自动扫描指定包下所有使用@Service,@Component,@Controller,@Repository的类并注册
示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@ComponentScan(value="com.atguigu",includeFilters = {
@Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
@Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}),
@Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})
},useDefaultFilters = false)
//excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
//includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件,
需设置useDefaultFilters = false
//FilterType.ANNOTATION:按照注解
//FilterType.ASSIGNABLE_TYPE:按照给定的类型;
//FilterType.ASPECTJ:使用ASPECTJ表达式
//FilterType.REGEX:使用正则指定
//FilterType.CUSTOM:使用自定义规则

1.3 @ComponentScans

可包含多个@ComponentScan
示例:@ComponentScans(value = {@ComponentScan,@ComponentScan,@ComponentScan})

1.4 @Lazy

单实例bean:默认在容器启动的时候创建对象;
懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;

1.5 @Conditional({Condition})

示例:@Conditional({WindowsCondition.class}),WindowsCondition是实现了Condition接口的类
按照一定的条件进行判断,满足条件给容器中注册bean,可定义在类名或者方法名上

1.6 注入组件

容器中注入组件的方式
1 @Bean:导入第三方的类或包的组件
2.ComponentScan:包扫描+组件的标注注解
3.@Import
4.使用Spring提供的FactoryBean(工厂Bean)进行注册

1.6.1 @Import()快速导入组件

可导入单个组件或者多个组件,id默认为全类名
示例:@Import(value={Dog.class,Cat.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})

1.6.2.使用ImportSelector自定义需要导入的组件

ImportSelector是一个接口,接口定义的方法为一个包含组件全类名的字符串数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {

//返回值,就是到导入到容器中的组件全类名
//AnnotationMetadata:当前标注@Import注解的类的所有注解信息
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// TODO Auto-generated method stub
//importingClassMetadata
//方法不要返回null值,否则会报空指针异常
return new String[]{"com.bernard.bean.Blue","com.bernard.bean.Yellow"};
}

}

1.6.3.使用ImportBeamDefinitionRegistrar返回自定义组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

/**
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类;
* 把所有需要添加到容器中的bean;
* 调用BeanDefinitionRegistry.registerBeanDefinition手工注册进来
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
if(definition && definition2){
//指定Bean定义信息;(Bean的类型,Bean。。。)
RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
//注册一个Bean,指定bean名
registry.registerBeanDefinition("rainBow", beanDefinition);
}
}

}

测试类
打印出所有注册到容器的bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyImportTest {
@Test
public void test01(){
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyImportConfig.class);

String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();

for (int i = 0; i < beanDefinitionNames.length; i++) {
String beanDefinitionName = beanDefinitionNames[i];
System.out.println(beanDefinitionName);
}

}
}

1.6.4.使用Spring提供的 FactoryBean(工厂Bean);

1)、默认获取到的是工厂bean调用getObject创建的对象
2)、要获取工厂Bean本身,我们需要给id前面加一个&,如:“&colorFactoryBean”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {

//返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
// TODO Auto-generated method stub
System.out.println("ColorFactoryBean...getObject...");
return new Color();
}

@Override
public Class<?> getObjectType() {
// TODO Auto-generated method stub
return Color.class;
}

//是单例?
//true:这个bean是单实例,在容器中保存一份
//false:多实例,每次获取都会创建一个新的bean;
@Override
public boolean isSingleton() {
// TODO Auto-generated method stub
return false;
}

}

注册示例:

1
2
3
4
@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}

获取示例

1
2
3
//工厂Bean获取的是调用getObject创建的对象
Object bean2 = applicationContext.getBean("colorFactoryBean");//获取getObject返回的bean
Object bean4 = applicationContext.getBean("&colorFactoryBean");//获取工厂bean本身

1.7 @Value

使用@Value可以为属性字段赋值
1、基本数值
2、可以写SpEL; #{}
3、可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值)

配置类
使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;
加载完外部的配置文件以后使用${}取出配置文件的值

1
2
3
4
5
6
7
8
9
10
@PropertySource(value={"classpath:/person.properties"})
@Configuration
public class MainConfigOfPropertyValues {

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

}

bean

1
2
3
4
5
6
7
8
9
10
public class Person {
@Value("张三")
private String name;

@Value("#{20-2}")
private Integer age;

@Value("${person.nickName}")
private String nickName;
}

1.8 @Autowired、@Resource、@Primary

  • 默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值
  • 如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找applicationContext.getBean(“bookDao”)
  • 自动装配默认一定要将属性赋值好,没有就会报错,如果注入容器中不存在的bean,可以使用@Autowired(required=false);
  • @Qualifier(“组件id”):使用@Qualifier指定需要装配的组件的id,而不是使用属性名
  • @Primary:让Spring进行自动装配的时候,默认使用首选的bean(使用该方式,注入组件时就不能使用@Qualifier了);
  • @Inject:需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
  • @Resource可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;没有能支持@Primary和@Autowired(reqiured=false)功能;

@Autowired:构造器,参数,方法,属性;都是从容器中获取参数组件的值

  • 如果@Autowired标注在方法/或参数位置上,Spring创建当前对象的时候,就会调用该方法完成赋值,方法使用的参数,会从ioc容器中获取,默认不写@Autowired效果是一样的,都能自动装配
  • 如果@Autowired标注在构造器上:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
  • 如果@Bean标注的的方法创建对象时,方法参数的值从容器中获取

补充:
@Autowired:Spring定义的;
@Resource、@Inject都是java规范

1.9 @Profile

指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件

  • 1)、加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
  • 2)、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
  • 3)、没有标注环境标识的bean,在任何环境下都是加载的;
    java配置MainConfigOfProfile.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    @PropertySource("classpath:/dbconfig.properties")
    @Configuration
    public class MainConfigOfProfile implements EmbeddedValueResolverAware{

    @Value("${db.user}")
    private String user;

    private StringValueResolver valueResolver;

    private String driverClass;

    @Bean
    public Yellow yellow(){
    return new Yellow();
    }

    @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/ssm_crud");
    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/scw_0515");

    dataSource.setDriverClass(driverClass);
    return dataSource;
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
    // TODO Auto-generated method stub
    this.valueResolver = resolver;
    driverClass = valueResolver.resolveStringValue("${db.driverClass}");
    }

    }
    激活方式:
  • 1、使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test
  • 2、java代码的方式激活某种环境,分为四步
    • 1)、创建一个applicationContext
    • 2)、设置需要激活的环境
    • 3)、注册主配置类
    • 4)、启动刷新容器

激活测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void test01(){
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext();
//1、创建一个applicationContext
//2、设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("dev");
//3、注册主配置类
applicationContext.register(MainConfigOfProfile.class);
//4、启动刷新容器
applicationContext.refresh();


String[] namesForType = applicationContext.getBeanNamesForType(DataSource.class);
for (String string : namesForType) {
System.out.println(string);
}

Yellow bean = applicationContext.getBean(Yellow.class);
System.out.println(bean);
applicationContext.close();
}

1.10 @Scope

在注册bean时,spring默认是单实例的,即scope=”singleton”,除此之外,常见的scope还有prototype、request、session作用域

  • prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。
  • request:同一次请求创建一个实例
  • session:同一个session创建一个实例

更多精彩内容:mrxccc