Spring 最重要的概念是 IOC 和 AOP,而他们究竟是什么,我一步一步来解开Spring的神秘面纱。
版本 5.1.X
引言
BeanFactory 简介
首先说明,作者这里说的是beanFactory而不是FactoryBean,这两个名字是颠倒的,但是功能是完全不一样的,不了解的可以参考我另外一篇文章。https://mp-new.csdn.net/mp_blog/creation/editor/117602060
beanFactory 从名字上理解,是Spring当中的工厂,能够去生产和获取我们的对象 。我们来看一下BeanFactory接口的结构图:
通过这个结构图我们就知道DefaultListableBeanFactory是一个功能最全的类。
先看一下Spring项目结构图,千万别被这些多给吓到,后面我们会一一分析。
项目启动
1、先看一下启动结构
其中AppConfig代码如下:
@Component
@ComponentScan(value = "my.study.spring.context")
public class AppConfig {
}
来看看我们的启动方法:
你没有看错,就只有一行代码,在这一行代码里完成了Spring的整个操作,实例化Spring容器,扫描类,解析类,实例化beanDefinition等等。
为了方便查看,我将会用图来表示,现在就相当于有了一个Spring环境:
我们来看看AnnotationConfigApplicationContext 构造方法里执行了什么操作。
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
//如果有父类会先调用父类的
this();
register(componentClasses);
refresh();
}
从AnnotationConfigApplicationContext的构造方法里执行的代码分为3步
-
调用父类的构造方法:
AnnotationConfigApplicationContext继承了GenericApplicationContext,所以说应该先看
GenericApplicationContext类的构造方法,如下图所示:
在GenericApplicationContext的构造方法里,new 了一个叫做,DefaultListableBeanFactory的类,就是beanFactory里功能最全的一个类。
我们来看看这个类里都定义了什么:
可以看到这里定义了这么多的属性,我把主要的记录下来,如图所示:
2、AnnotationConfigApplicationContext自身的构造方法
AnnotationConfigApplicationContext无惨构造器,主要是注册了6个bean到DefaultListableBeanFactory,这6个bean是Spring自带的。我们先来看看
AnnotatedBeanDefinitionReader这个类做了什么,点开它。
需要注意的是:
this.reader = new AnnotatedBeanDefinitionReader(this);
这个方法的所在类是AnnotationConfigApplicationContext,这里传的是this,
而到了AnnotatedBeanDefinitionReader类的构造方法里
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) { this(registry, getOrCreateEnvironment(registry)); }
用的却是BeanDefinitionRegistry来接受参数,这一现象说明了,AnnotationConfigApplicationContext与BeanDefinitionRegistry是一样的,BeanDefinitionRegistry也是Spring的一个环境,我们来修改图的信息:
我们接着往下看,点开这个this()方法:
this(registry, getOrCreateEnvironment(registry));
接着点开:
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
是一个空壳方法,接着看下一个方法
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) { registerAnnotationConfigProcessors(registry, null); }
这个方法里主要是注册了6个bean
先获取了DefaultListableBeanFactory工厂,而后依次判断添加这几个bean.
怎么添加的呢?请注意这个方法:registerPostProcessor(registry, def, xxx);
我们看这个方法内部:registry.registerBeanDefinition(beanName, definition);
DefaultListableBeanFactory#registerBeanDefinition,是工厂类的方法,
这个方法里,主要是以下代码(无关代码做了删除)
走到这里,我们的beanDefinitionMap、beanDefinitionNames都有了相应的数据。
其中有一个bean很重要很重要,请记住它,我们后面说:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
现在的结构图:
我们现在回到AnnotationConfigApplicationContext的无惨构造方法就讲完了
下面说说,AnnotationConfigApplicationContext的有参构造方法,
上面这个方法是从AnnotationConfigApplicationContext被创建时掉进来的
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
所以说,此时:componentClasses就是AppConfig,由于我们说完了this()方法,下面说
register(componentClasses);这个方法,让我们进入到这个方法里:
这个方法是一个空壳方法,里面调用了另外一个方法:
这里面循环遍历,componentClasses,此时只有一个AppConfig,我们看
registerBean()方法。
registerBean()方法,也是个空壳方法,呵、Spring啊!!! 我们看里面调用了:doRegisterBean()方法。
这里其实有一个面试题,就是如何把一个xxx.class变成一个beanDefinition,其中有一种方法就是直接通过BeanDefinition的构造方法转换,还有一种这里先不讨论。此时的
AnnotatedGenericBeanDefinition就是我们得到AppConfig类。我们接着往下看,处理作用域,bean名字等,最要还是最后一行代码。
我注释写的很明白,其实就是将Appconfig注册到BeanFactory中,我们来看是怎么注册的。
看上面的代码,就是通过
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
将AppConfig注册到bean工厂的。这个方法熟悉不熟悉?没错,就是在注入那6个Springbean的时候调用的方法,这里也将AppConfig注册到Bean工厂。到此为此,BeanFactory里就有了7个对象。7对象中有一个是AppCoonfig,一个是ConfigurationClassPostProcessor(但是这个类在Spring里的名字是internalConfigurationAnnotationProcessor),剩余的5个是BeanPostProcessor后置处理器
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { //如果有父类会先调用父类的 this(); register(componentClasses); refresh(); }
文章说到这里,AnnotationConfigApplicationContext的构造方法还剩一个refresh()就说完了,而refresh(),这个方法内容较多,我会另外写一篇文章专门写refresh()方法的内容。