Spring官方文档对@Configuration的介绍:
@Configuration is a class-level annotation indicating that an object is a source of bean definitions. @Configuration classes declare beans via public @Bean annotated methods. Calls to @Bean methods on @Configuration classes can also be used to define inter-bean dependencies.
@Configuration是类级别的注解,指示一个对象是Bean定义(Bean Definition)的来源。@Configuration类通过公共@Bean注释方法声明Bean。@Configuration类允许通过调用同一个类的其他@Bean方法来定义Bean的依赖关系。
public class ConfigurationBean {
}
public interface ConfigurationService {
public void test(ConfigurationBean configurationBean);
}
public class ConfigurationServiceImpl implements ConfigurationService {
public ConfigurationServiceImpl(ConfigurationBean configurationBean) {
System.out.println("ConfigurationServiceImpl====" + configurationBean);
}
@Override
public void test(ConfigurationBean configurationBean) {
System.out.println("test====" + configurationBean);
}
}
@Configuration
public class AppConfiguration {
@Bean
public ConfigurationService configurationService() {
return new ConfigurationServiceImpl(configurationBean());
}
@Bean
public ConfigurationBean configurationBean() {
return new ConfigurationBean();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfiguration.class);
// System.out.println(context.getBean("configurationService"));
}
}
以上的代码等价于:
<beans>
<bean id="configurationBean" class="ConfigurationBean"/>
<bean id="configurationService" class="ConfigurationServiceImpl">
<constructor-arg ref="configurationBean">constructor-arg>
bean>
beans>
@Bean注解用于指示方法实例化,配置和初始化要由Spring IoC容器管理的新对象。@ Bean注释与
元素具有相同的作用。
这里获取到的AppConfiguration是一个Cglib代理对象,那这个代理对象是如何生成的呢?
进入AbstractApplicationContext的refresh方法,
在执行invokeBeanFactoryPostProcessors(beanFactory)方法前是普通的AppConfiguration类,执行完invokeBeanFactoryPostProcessors方法后,AppConfiguration是一个增强过的Cglib代理对象。
AbstractApplicationContext.invokeBeanFactoryPostProcessors
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
currentRegistryProcessors是ConfigurationClassPostProcessor,是@Configuration类的后置处理器。
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry
ConfigurationClassPostProcessor.processConfigBeanDefinitions
(1)如果在未使用@Configuration注释的类中声明@Bean方法,则将它们在“lite”模式下进行处理。
(2)如果在使用@Configuration注释的类中声明@Bean方法,则将他们在"full"模式下进行处理。
(3)在"lite"模式下,无法声明Bean之间的依赖关系。在“full”模式下,跨方法引用将被重定向到容器的生命周期管理。也就是,如果类添加了@Configuration注解,类中的一个Bean方法A引用另一个Bean方法B,会到Spring容器中找B方法创建的Bean,而不是调用方法B再新创建一个Bean。
进入ConfigurationUtils的checkConfigurationClassCandidate方法,meta的类型是StandardAnnotationMetadata,判断meta是否标注了@Configuration注解。如果类标有@Configuration注解,该类对应的BeanDefinition的元数据会加上一个属性(org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass, full);
判断是否标注了@Configuration注解
ConfigurationClassPostProcessor.enhanceConfigurationClasses
用ConfigurationClassEnhancer对AppConfiguration进行增强,如果父类configClass(class gdut.ff.configuration.AppConfiguration)与生成的子类(class gdut.ff.configuration.AppConfiguration E n h a n c e r B y S p r i n g C G L I B EnhancerBySpringCGLIB EnhancerBySpringCGLIBf5d6df32)不一样的话,就将BeanDefinition中的beanClass的值设置为生成的代理对象(class gdut.ff.configuration.AppConfiguration E n h a n c e r B y S p r i n g C G L I B EnhancerBySpringCGLIB EnhancerBySpringCGLIBf5d6df32)
ConfigurationClassEnhancer.enhancer方法用于创建AppConfiguration的一个cglib子类对象。
创建一个cglib实例
创建子类对象
今天断点看Spring源码的时候发现,无法找到org.springframework.cglib包下的代码,原来这部分代码是Spring打包的时候从net.sf.cglib拿来的,详情可以参看spring-core-5.0.6.RELEASE-sources.jar中java源代码不全