前段时间旁听了某课堂两节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));
}