Spring @Configuration流程概述

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);
        }
    }
}

3. 资料参考

Spring Bean生命周期
Spring核心流程梳理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值