本文整理Spring的IOC部分。
文章目录
前言
直接进入ApplicationContext部分,BeanFactory要不要写,后边我再想想。
一、ApplicationContext的实现
ApplicationContext有两种使用方法,注解和XML。
对应的实现也有个两个实现类AnnotationConfigApplicationContext和FileSystemXmlApplicationContext。
现在大家都使用注解的方法,这里就先从注解展开,但是个人建议还是要看一下XML的实现,因为XML比注解早,为了兼容,这两种代码大量纠缠在一起,如果单纯只了解一种,可能读源码的时候会有不理解的地方。
二、AnnotationConfigApplicationContext的使用
public class MainStart {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
Car car = (Car)context.getBean("car");
System.out.println(car.getName());
}
}
这就是一个AnnotationConfigApplicationContext的使用Demo,非常简单,所以我们可以理解,容器的初始化过程已经完成了所有Bean管理的工作。
1.AnnotationConfigApplicationContext的初始化
代码如下(示例):
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
一共三行代码,分别讲。
2.this()初始化了三个组件
this(); 调用了无参构造函数
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
而无参构造函数调用之前又会调用父类的无参构造函数。
public class AnnotationConfigApplicationContext extends GenericApplicationContext
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
到这里,this的功能就完成了,如标题所述,初始化了三个组件beanFactory,reader,scanner。
beanFactory:用作容器,是真正存放Bean的地方。
reader:用于解析BeanDefinition。
scanner:用于接收路径,扫描包。
到这里知道大概就可以了,后边会逐渐深入。
3.register(componentClasses)注册BeanDefinition
这里将完成@Configuration标记的配置类的解析,本部分将另起一文。
4.refresh()中会完成其他工作
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//1:准备刷新上下文环境
prepareRefresh();
//2:获取告诉子类初始化Bean工厂 不同工厂不同实现
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//3:对bean工厂进行填充属性
prepareBeanFactory(beanFactory);
try {
// 第四:留个子类去实现该接口
postProcessBeanFactory(beanFactory);
// 调用我们的bean工厂的后置处理器. 1. 会在此将class扫描成beanDefinition 2.bean工厂的后置处理器调用
invokeBeanFactoryPostProcessors(beanFactory);
// 注册我们bean的后置处理器
registerBeanPostProcessors(beanFactory);
// 初始化国际化资源处理器.
initMessageSource();
// 创建事件多播器
initApplicationEventMulticaster();
// 这个方法同样也是留个子类实现的springboot也是从这个方法进行启动tomcat的.
onRefresh();
//把我们的事件监听器注册到多播器上
registerListeners();
// 实例化我们剩余的单实例bean.
finishBeanFactoryInitialization(beanFactory);
// 最后容器刷新 发布刷新事件(Spring cloud也是从这里启动的)
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
这个方法中要做的事情还是很复杂的,字面意思,这个方法就是刷新,也就是几乎所有重要工作都在这里。里面的重要方法,我将分别写一篇博文来说明。