熟悉Spring的朋友可能都知道,Spring容器,是Spring框架实现其两大核心思想,IOC,AOP的基础,平时我们可能只是会享受容器带给我们的便利,确对容器的了解知之甚少,今天,我们就来通过Spring底层源码来分析Spring容器的构造过程,这将使我们对Spring的认识再上一个台阶,让我们更加了解我们的“对象”。
容我再哔哔一句,在我看来:
Ioc的实现,可以说一大部分功劳是Spring容器的。
而AOP的实现,可以说一小部分功劳是Spring容器的,但是也是不可或缺的。
下面就让我们进入Spring容器创建的源码分析环节!
首先,我们来看看我们如何触发Spring容器的创建:
@Test
public void fun1(){
//使用配置文件,创建容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(extConfig.class);
//关闭容器
((AnnotationConfigApplicationContext) applicationContext).close();
}
可以看出来,我们使用的是带有参数的AnnotationConfigApplicationContext("配置类.class")。那么我们通过Debug跟踪容器的创建过程。会发现其实其底层调用了三个方法:
下面这段是Spring的源码截取出来的:
public AnnotationConfigApplicationContext(Class... annotatedClasses) {
//调用容器的无参构造器,创建容器
this();
//向容器中注册配置类
this.register(annotatedClasses);
//调用refresh()方法,该方法执行完毕则Spring容器的创建和初始化就已经完成了
this.refresh();
}
我们只需要关注refresh()方法即可,点进refresh()方法,会看到如下的逻辑:
今天我们的主要任务就是要研究研究这些方法背后的逻辑,搞清楚它们背后的逻辑,也就掌握了Spring容器的创建和初始化。
第一阶段——Spring容器创建的第一阶段就是容器的创建及一些准备工作。该阶段包含以下四个方法。
1.prepareRefresh()方法的执行【为beanFactory的刷新做前置准备】。
- initPropertySources()方法的执行【设置一些容器的初始化参数】:点进去后我们会发现,这个方法是空的,在我看来这种方法就是留给后来人增强某些特定功能用的,通过继承当前类,对该方法进行重写,然后达到增强容器功能的目的。
- getEnvironment().validateRequiredProperties();【校验自己设置的这些容器初始化参数的设置是否符合要求】:因为前面的设置初始化参数方法都是空的,所以这里的校验也是虚的,因为根本就不能设置容器的初始化参数。
- earlyApplicationEvents = new LinkedHashSet();【创建一个集合来保存容器创建早期的一些事件,以便待容器创建完毕后多播器将这些事件派发出去】
2.ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();【获得刷新后的beanFactory】。
1>refreshBeanFactory()[GenericApplicationContext.class的该方法];【刷新beanFactory容器】
1)点进去后会发现,在构造函数中,存在如下代码,this.beanFactory = new DefaultListableBeanFactory();【创建容 器】。
2)给容器设置一个序列化过的id,然后返回刚刚创建成功的这个容器。
3.prepareBeanFactory(beanFactory);【为创建新创建的好的beanFactory设置一些它作为一个容器应该拥有的东西】。
1>设置几个东西
1)设置类加载器。
2)设置标准的Bean表达式解析器。
2>添加一个组件【一个Bean后处理器】。
3>禁用几个接口实现类的自动注入功能。
1)EnvironmentAware
2)ApplicationEventPublisherAware
3)ApplicationContextAware
4)ResourceLoaderAware
4>添加一些接口实现类的自动注入功能
1)BeanFactory
2)ResourceLoader
3)ApplicationContext
4)Application