Spring源码解读之BeanFactoryPostProcessor的处理

前段时间旁听了某课堂两节Spring源码解析课,刚好最近自己又在重新学习中,便在这里记录一下学习所得。我之前写过一篇博文,是介绍BeanFactoryPostProcessor跟BeanPostProcessor是如何发挥作用的,当时觉得讲的还行,但是现在看来,太粗劣了,很多地方没涉及到,而且重点都被我忽略了,简直就是蠢得不行。现在就用这篇文章弥补一下前文中对BeanFactoryPostProcessor的讲解,争取把重点讲到,至于BeanPostProcessor,由于涉及到的东西太多,限于本人目前的水平只能作罢,待后面感悟成熟了再来补充。

我们以AnnotationConfigApplicationContext为例来构建测试类,先附上此次打断点调试的三个简约到极致的测试类:

public class SpringTest {

public static void main(String[] args) {
        // 从这两行代码,实地跟踪考察Spring中的流程
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanConfig.class);
        applicationContext.getBean(Teacher.class).teach();
    }
}

package myPackage;
import org.springframework.stereotype.Service;

@Service
public class Teacher {
    public Teacher () {
        System.out.println("Teacher init");
    }
    public void teach () {
        System.out.println("teach");
    }
}

1 package myPackage;
2 import org.springframework.context.annotation.ComponentScan;
3
4 @ComponentScan("myPackage")
5 public class ScanConfig {
6 }

1、洞悉启动容器时的准备工作

熟悉一些Spring的道友应该都知道,refresh方法中的invokeBeanFactoryPostProcessors方法实现了对BeanFactoryPostProcessor实现类的处理。大家如果只看invokeBeanFactoryPostProcessors方法的话,不会发现有何异常之处,此方法虽然较长,但是处理逻辑很清晰,先对重写了BeanFactoryPostProcessor的子接口BeanDefinitionRegistryPostProcessor方法的实现类进行处理,后对重写了BeanFactoryPostProcessor的方法的实现类做了处理。但是如果心细的话,你会发现问题,Spring是如何将@ComponentScan("myPackage")注解发挥作用的?这时带着这样的问题,我们再回过头来看容器的构造方法,就会在这平实的表面下发现意想不到的 "杀机"。

1 public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
2        this();
3        register(annotatedClasses);
4        refresh();
5    }

通过这个构造方法可以知道,在第二行将我们的测试类ScanConfig 注册进了容器中,但这只是注册,注册之后是如何调用如何实现了@ComponentScan("myPackage")这个注解的包扫描的呢?这时我们将目光锁定this()方法。点进去后发现是这样的:

1 public AnnotationConfigApplicationContext() {
2        this.reader = new AnnotatedBeanDefinitionReader(this);
3        this.scanner = new ClassPathBeanDefinitionScanner(this);
4    }

在第二行新建reader对象时,调用了这个构造方法:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

其中的第六行,最终调用了AnnotationConfigUtils#registerAnnotationConfigProcessors方法,而就是在这个方法中完成了对多个重要Bean的注册,跟我们关系比较大的有以下几个:

// BeanDefinitionHolder只是存放BD的,里面有三个属性:BD对象、beanName以及别名组成的String[]
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
        // 注册最关键的类,对应的类为ConfigurationClassPostProcessor,父类的父类是BeanFactoryPostProcessor
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            // 将BD注入进容器中,没经过什么处理,只是放入了DefaultListableBeanFactory中的beanDefinitionMap跟存放beanName的list中
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
        // 此类实现了BeanPostProcessor,用于处理@Autowired、@Value注解
        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
        // 此类也实现了BeanPostProcessor,用于处理有@Required注解的方法
        if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/7f67ec468e0b602927184517c72adefa.html