@Configuration注解
在使用spring的时候,如果我们加了一个配置类,通常会在配置类上加上一个@Configuration注解,这个注解的作用,是我们要探讨的内容
结论:
1.加了@Configuration注解的类,我们称之为全配置类,这里之所以这么叫,在后面我会解释(这里所说的全配置类,我只是为了和普通类区分开来)
2.对于加了@Configuration的配置类,spring会为该类生成代理对象(CGLIB代理)
3.配置类加与不加@Configuration,都会注入bean,只是,通过@Bean在配置类中注入的bean,有可能是非单实例的bean
应用
先看下我自己的写的demo
@Configuration
@ComponentScan("com.study.extension.configuration")
public class AppConfig {
@Bean
public TestBean01 testBean01(){
System.out.println("初始化bean01");
return new TestBean01();
}
@Bean
public TestBean02 testBean02(){
System.out.println("初始化bean02");
testBean01();
return new TestBean02();
}
}
public class TestBean01 {
}
public class TestBean02 {
}
public class TestConfiguration {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(ac.getBean(AppConfig.class));
}
}
这上面是我的源码,下面我录的一个gif,分别展示了appConfig类中加@Configuration注解和不加@Configuration注解的区别:
可以看到:
如果加了@Configuration注解,那么,在我们打印出来的AppConfig对象就是一个CGLIB代理对象
com.study.extension.configuration.AppConfig$$EnhancerBySpringCGLIB$$b954b13@6e0dec4a
并且,在配置类中,只会打印一次 “初始化bean01”
如果不添加@Configuration注解,那么,我们打印出来的AppConfig对象就是一个普通的bean
com.study.extension.configuration.AppConfig@b7f23d9
并且,在配置类中,会打印两次 “初始化bean01”
原因说明
我先把这里的原因解释明白,后面再用源码来说明
- spring在源码中的某一步,会对配置类进行解析,如果配置类加了@Configuration注解,就会将对应beanDefinition对象的configurationClass属性设置为full;否则,设置为lite
- 在spring初始化的过程中,在某一步,spring会为加了@Configuration注解的类,生成代理对象,这是我们看到为什么打印出来的对应一个是代理对象,一个是普通类的原因;这里代理对象的生成,依赖于第一步的解析
- 如果配置类是代理对象,在调用配置类中的方法的时候,就会判断当前bean是否已经在容器中,如果已经在容器中了,就直接从容器中获取,而不会初始化;但是如果配置类是普通对象,在调用配置类中的方法的时候,就会直接调用对应的方法
这里说的第一步是在:org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
这个方法中完成的
第二步,动态对象对象的生成,是在org.springframework.context.annotation.