注解解析原理:ConfigurationClassPostProcessor及ConfigurationClassParser

1. 知识准备:

1.1 AnnotationConfigUtils

在读取beanDefination的时候,调用自定义的解析器,对于AnnotationConfigBeanDefinitionParser和ComponentScanBeanDefinitionParser会调用AnnotionCOnfigUtils.java 的registerAnnotationConfigProcessors,把beanName注册进去。

//==================
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor...


AnnotationConfigUtils.java
{
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =			"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
   .. ..
 // 注册内部管理的用于处理@configuration注解的后置处理器的bean
//****************重点*****************
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(..){
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			// 注册BeanDefinition到注册表中  。ConfigurationClassPostProcessor到注册表中(以后可以实例化了)
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
    
   .....       
	}    
}   
1.2 调用时机

其中第一和第二,是处理xml配置(component-scan和annotation-config)的时候,注册bfpp等定义信息的。第三种是注解启动时候注册各种bd信息的。

==========================注解工具注册====================
    
 调用registerAnnotationConfigProcessors(..)注册bd
// 根据条件,选择注册bean的定义信息
1. ConfigurationClassPostProcessor(bfpp) 
2. AutowiredAnnotationBeanPostProcessor(bpp)
3. CommonAnnotationBeanPostProcessor(bpp)
4. EventListenerMethodProcessor(bfpp)   
5. DefaultEventListenerFactory 等
    
在下面三个地方调用了:    
1. 
//registerBeanDefinitionParser("annotation-config", new //AnnotationConfigBeanDefinitionParser());
    
AnnotationConfigBeanDefinitionParser.java#parse{
    //注册注解配置处理器 bean信息
Set<BeanDefinitionHolder> processorDefinitions =
	//注册bfpp和bpp
  AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);   
}
//根据标签解析。注册解析器
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());



2.
//处理 <component:scan base-package.. 等xml 配置
// registerBeanDefinitionParser("component-scan", new //ComponentScanBeanDefinitionParser());
    
ComponentScanBeanDefinitionParser.java#parse{
    
    ClassPathBeanDefinitionScanner#doScan(); 
    // 把扫描到的bd放进容器 
    // 注册系统bd信息
    AnnotationConfigUtils.registerAnnotationConfigProcessors(..)
  
  } 

3.本类 registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
		registerAnnotationConfigProcessors(registry, null);
}
3.1 使用注解启动的时候,使用的。AnnotationConfigApplicationContext启动的
    //在构造方法中调用了
   	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
      // 。。。
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

2. 源码分析

2.1 开始

refresh()

-> invokeBeanFactoryPostProcessors

  // 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName
    String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

//实例化bfpp
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
...
//调用
 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
 -> 
PostProcessorRegistrationDelegate.java    	 postProcessor.postProcessBeanDefinitionRegistry(registry);

到达ConfigurationClassPostProcessor.java

	 // 定位、加载、解析、注册相关注解
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		//....
		processConfigBeanDefinitions(registry);
	}

到达ConfigurationClassPostProcessor.java

/**
	 * 构建和验证一个类是否被@Configuration修饰,并做相关的解析工作
	 *   获取所有的beanDefination对象,然后遍历,查看这些类上面的注解
	 */
	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		String[] candidateNames = registry.getBeanDefinitionNames();
		// 遍历所有要处理的beanDefinition的名称,筛选对应的beanDefinition
        //被@Component已经注册过了
		for (String beanName : candidateNames) {
		do {
			// 解析带有@Controller、@Import、@ComponentScan、@Bean的BeanDefinition
			// ConfigurationClassParser parser 
			parser.parse(candidates);

			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			// 将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器
			this.reader.loadBeanDefinitions(configClasses);
			}
	}

转移到ConfigurationClassParser.java类。核心处理方法在doProcessConfigurationClass()中。

=======>ConfigurationClassParser.java#parse(..){
 //根据不同的类型,调用重载的parse方法
}
以注解为例子
->parse()
-->processConfigurationClass()
--->doProcessConfigurationClass(){
	//1. 递归处理内部类,符合条件的加入到候选。遍历处理
	2. 处理@PropertySource 注解
	3. 处理处理@ComponentScan或者@ComponentScans注解,通过ComponentScanAnnotationParser#parse(..),进而调用ClassPathBeanDefinitionScanner#doScan(..),解析的是@Component及其子类,解析到了所有的scannedBeanDefinitions,判断是,是不是配置类,是配置类,再递归处理
	4. 处理@Import注解
	5. 处理@ImportResource注解
	6. 处理@Bean注解的方法
	7. 处理接口,jdk8支持接口@Bean注解
}
// 到此,注解解析完毕
2.2 源码流程

AbstractApplicationContext.java#invokeBeanDefinitionRegistryPostProcessors
-》PostProcessorRegistrationDelegate.java#invokeBeanDefinitionRegistryPostProcessors
-》PostProcessorRegistrationDelegate.java#postProcessor(ConfiguratiionClassPostProcessor).postProcessBeanDefinitionRegistry(registry);
-》ConfiguratiionClassPostProcessor.java#processConfigBeanDefinitions(registry);
-》ConfiguratiionClassPostProcessor.java#parser.parse(candidates);这里的parser就是ConfigurationClassParser类型,解析完,从列表bd放到工厂中;
-》ConfigurationClassParser.java#processConfigurationClass(…);这里放到列表中
-》ConfigurationClassParser.java#doProcessConfigurationClass(…),这里开始解析各种注解,然后configurationClasses.put(configClass, configClass);这里是将
@Import注解标记的普通类,放到列表,@ComponentScan扫描到的被标记的,然后调用processConfigurationClass()
-》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值