TOP

Spring源码解读之BeanFactoryPostProcessor的处理(一)
2019-09-03 03:40:14 】 浏览:73
Tags: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.conditioneva luator = new Conditioneva luator(registry, environment, null);
? ? ? ? AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
? ? }


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


// BeanDefinitionHolder只是存放BD的,里面有三个属性:BD对象、beanName以及别名组成的String[]
? ? ? ? Set beanDefs = new LinkedHashSet(4);
? ? ? ?
Spring源码解读之BeanFactoryPostProcessor的处理(一) https://www.cppentry.com/bencandy.php?fid=54&id=249487

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Spring中的循环依赖解决详解 下一篇@Import与@ImportResource注解的..

kafka-
kafka ? Partit
解决android studio
Kafka史上最详细原理
Error while fetchin
【Kafka】安装与快速
? ? &
flume读取日志数据写
Authentication plug
Flume 自定义source
flume ? 三大核
ICC副本>>>
愚公移山 ?
Hbase架构 ? Hb
5 hbase-shell + &
Hbase ? MapRed
MetaException(messa
Exception in thread
HIVE metastore Dupl
-->