1. 开始
在Spring核心流程梳理中我们已经介绍了,Spring的核心流程都被封装在了模板方法refresh中。
但是AnnotationConfigApplicationContext解析BeanDefinition的方式和ClassPathXmlApplicationContext还是不同。
ClassPathXmlApplicationContext是在refresh方法中通过调用prepareBeanFactory逻辑来处理。
而AnnotationConfigApplicationContext在构造逻辑中就开始处理解析BeanDefinition逻辑。
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionConfig.class);
从AnnotationConfigApplicationContext入口,实际解析逻辑在AnnotatedBeanDefinitionReader的doRegisterBean方法中。
主要就是解析注册BeanDefinition,包括处理@Conditional条件判断、作用域Scope、懒加载@lazy、@Primary等逻辑。
2. ConfigurationClassPostProcessor
Spring是通过BeanFactoryPostProcessor:ConfigurationClassPostProcessor来处理Configuration注解的。
我们已经知道,Spring处理BeanFactoryPostProcessor是通过refresh的invokeBeanFactoryPostProcessors方法做为入口了。
逻辑执行通过代理:PostProcessorRegistrationDelegate实现。
当然,最终的逻辑还是通过ConfigurationClassPostProcessor来执行。
其中2个重要的方法:
processConfigBeanDefinitions方法解析@Configuration的类的信息:
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 这个时候BeanDefinition已经继续完了,所以这里可以获取容器中的所有BeanDefinition了
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {//找出容器中所有被@Configuration注解的类的BeanDefinition,包装成BeanDefinitionHolder
if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 处理@Order注解,根据优先级排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// 通过ConfigurationClassParser解析 @Configuration 类
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 解析@Import、@Bean等注解
this.reader.loadBeanDefinitions(configClasses);
}
enhanceConfigurationClasses方法为Configuration设置代理类:
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
MethodMetadata methodMetadata = null;
// 通过cglib给Configuration生成代理类逻辑
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
Class<?> configClass = beanDef.getBeanClass();
// 最主要的方法是注册了一个BeanMethodInterceptor回调类,来处理@Bean注解
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
beanDef.setBeanClass(enhancedClass);
}
}
}