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的类的信息:
1public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { 2 // 这个时候BeanDefinition已经继续完了,所以这里可以获取容器中的所有BeanDefinition了 3 4 List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); 5 String[] candidateNames = registry.getBeanDefinitionNames(); 6 7 for (String beanName : candidateNames) {//找出容器中所有被@Configuration注解的类的BeanDefinition,包装成BeanDefinitionHolder 8 if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { 9 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); 10 } 11 } 12 13 // 处理@Order注解,根据优先级排序 14 configCandidates.sort((bd1, bd2) -> { 15 int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); 16 int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); 17 return Integer.compare(i1, i2); 18 }); 19 20 // 通过ConfigurationClassParser解析 @Configuration 类 21 ConfigurationClassParser parser = new ConfigurationClassParser( 22 this.metadataReaderFactory, this.problemReporter, this.environment, 23 this.resourceLoader, this.componentScanBeanNameGenerator, registry); 24 25 // 解析@Import、@Bean等注解 26 this.reader.loadBeanDefinitions(configClasses); 27}
enhanceConfigurationClasses方法为Configuration设置代理类:
1public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) { 2 Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>(); 3 for (String beanName : beanFactory.getBeanDefinitionNames()) { 4 BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); 5 Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE); 6 MethodMetadata methodMetadata = null; 7 8 // 通过cglib给Configuration生成代理类逻辑 9 ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(); 10 for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) { 11 AbstractBeanDefinition beanDef = entry.getValue(); 12 beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); 13 Class<?> configClass = beanDef.getBeanClass(); 14 // 最主要的方法是注册了一个BeanMethodInterceptor回调类,来处理@Bean注解 15 Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader); 16 if (configClass != enhancedClass) { 17 beanDef.setBeanClass(enhancedClass); 18 } 19 } 20}