开篇
本篇文章是Spring源码分享的第三篇,有了前两篇分享的基础,从这篇开始进行源码的分析。
因为是做源码分析且是逐行解析,以后的文章我会先把代码注释贴出来,然后最后做个总结。
通过这篇文章你可以获得什么
- 了解new AnnotationConfigApplicationContext() 时发生了什么
正文
启动一个Spring工程很简单,我们只需要main方法中写如下三行代码:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 内部调用的Reader的方法
context.register(Config.class, NameConfig.class);
context.refresh();
或者直接把上边三行代码替换成一行:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class, NameConfig.class);
- 我们现在就来研究一下当我们在代码中写了
new AnnotationConfigApplicationContext();
这行代码时,Spring帮我们做了一些什么?
AnnotationConfigApplicationContext
通过这个类的图我们可以看到它继承了GenericApplicationContext
和AbstractAutowireCapableBeanFactory
。那我们知道当我们进行new的时候实际上会先执行父类的构造方法。那我们再来看一下它的父类中做了什么?
GenericApplicationContext的构造方法
代码块如下:
/**
* 创建一个 beanFactory
* Create a new GenericApplicationContext.
* @see #registerBeanDefinition
* @see #refresh
*/
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
可以看到在这初始化了一个beanFactory。
DefaultListableBeanFactory的构造方法
最终调用的是抽象类的构造方法的实现:
/**
* Create a new AbstractAutowireCapableBeanFactory.
*/
public AbstractAutowireCapableBeanFactory() {
// 空实现
super();
// 添加依赖注入的接口
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
看代码发现就是向工厂的集和中 添加了一些忽略装配的接口。
/**
* Dependency interfaces to ignore on dependency check and autowire, as Set of
* Class objects. By default, only the BeanFactory interface is ignored.
*/
private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<>();
AnnotationConfigApplicationContext 自己的构造方法
/**
* 创建注解配置类型的额上下文 本身也是一个注册中心
* 会调用父类方法 创建 beanFactory
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
// 注解bean定义信息解析器
// 添加工厂的后置处理器 和bean的后置处理器
this.reader = new AnnotatedBeanDefinitionReader(this);
//扫描指定包下的bean转成BeanDefinition
this.scanner = new ClassPathBeanDefinitionScanner(this)