额…突然发现对spring框架源码已经模糊了,利用这个雷暴天气的周末重新过了一遍spring framework框架的源码,下面是我所理解的spring框架
spring是一个简化开发的框架,所谓框架就是一套开发骨架(模板),所以spring核心流程就是基于模板模式开发出来的。然后在多个地方留好了扩展点,几乎所有跟spring整合的组件都是基于这些扩展点来的。本文就是我个人从AnnotationConfigApplicationContext这个上下文对象开始对spring这个抽象骨架的理解,从高层次上理解整个spring俯瞰图。
先上一个自我总结的抽象架构图
spring framework框架主流程(基于AnnotationConfigApplicationContext上下文对象)
从以下这段代码开始就是spring启动的全过程:
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext();
ac.refresh();
- 当初始化AnnotationConfigApplicationContext类时,会在构造函数中new出两个类:
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
一、AnnotatedBeanDefinitionReader:
注册了很多重要的beanFactoryPostProcess 和 beanPostProcess后置处理器,如:
1、ConfigurationClassPostProcessor这个处理器作用是处理配置类和import进入的类
2、AutowiredAnnotationBeanPostProcessor这个处理器是专门处理autowire、lookup这类注解的
3、CommonAnnotationBeanPostProcessor这个处理器作用是处理@Resource、@PostConstruct和@PreDestroy等注解的
等多个后置处理器,这个处理器bean的名字都是org.springframework.xxx.internalxxx命名,是后面整个上下文注解启动的解析引擎
二、ClassPathBeanDefinitionScanner:
主要就是用于扫描包(写代码时主动指定的包路径!spring默认的扫描器在后面会再new一个,这个对象只会扫描程序员写代码时主动指定的包路径)
- refresh()方法:
上下文类实例化完成后,配置了些指定的东西后会调用refresh()方法,这个就是spring最核心的方法,整个启动流程都在这个方法内完成
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
}
}
}
1、prepareRefresh():这个方法内只是设置了启动时间,激活标识位,不重要
2、obtainFreshBeanFactory()->refreshBeanFactory()刷新工厂,实例化默认的工厂类DefaultListableBeanFactory并调用loadBeanDefinitions()方法,这个方法内重新实例化了reader、scanner扫描和读取相应的beanDefinition加入到工厂
3、prepareBeanFactory():加载了工厂的一些属性,如:StandardBeanExpressionResolver spEl解析器、ResourceEditorRegistrar类型转换器、加入ApplicationContextAwareProcessor这个BeanPostProcessor(专门实现回调**aware接口的),加入三个环节变量类environment
4、postProcessBeanFactory():这个方法暂时是无实现的,其子类如xxxWebApplicationContext就会有具体实现,一般都是加上一个beanPostProcess(加入某些功能点)
5、invokeBeanFactoryPostProcessors():把配置上的bean全部解析成beanDefinition存到beanFactory上了。非常重要的方法,相当于把整个应用的配置解析好了放入BeanDefinitionMap里面
先把程序员自己添加的BeanDefinitionRegistryPostProcessor先回调,然后实例化了ConfigurationClassPostProcessor这个类,用来专门处理配置类的(加了@Configuration)
会对每一个配置类进行解析,获取所有配置信息,先调用BeanDefinitionRegistryPostProcessor再调用BeanFactoryPostProcessor
基于已经有很多大佬写好了,回顾时参考:
Spring IoC源码解析之invokeBeanFactoryPostProcessors
6、registerBeanPostProcessors():
实例化三个重要的beanPostProcess:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor ,很重要,这几个处理器用于后面把bean上面的注解解析执行想要操作的引擎
当然如果你在代码中也有定义beanPostProcess的话,也会在这个阶段实例化
7、initMessageSource():初始化国际化i18n
8、initApplicationEventMulticaster():初始化应用事件广播器
9、onRefresh();默认无实现,在web子类中有对应的实现
10、registerListeners():注册实现了ApplicationListener接口的监听器
11、finishBeanFactoryInitialization()😗***最最最重要的方法,大部分自己写的bean都会在这里实例化+初始化。这里有详细讲解:Spring IoC源码解析之getBean
12、finishRefresh():发布refresh完成事件
到这里整个spring就启动完成了,下面的方法就是发生异常关闭容器做的一些处理,一般都不会去探讨
总结:
上面简述了整个spring启动的过程,当然只是纯粹的启动。但是如果了解启动过程中每一步在干什么,就能对spring做无限扩展了。
例如:理解了spring中对于扩展最重要的接口:BeanFactoryPostProcessor和BeanPostProcesser,并知道在哪个时机会回调,我们就可以自己编写相应的实现类交给spring,就会在启动时给你调用,完成你想要的扩展了
spring中最重要的ioc和aop都是这样来做的:
spring ioc依赖了AutowiredAnnotationBeanPostProcessor这个beanPostProcess来实现的
spring aop依赖了AspectJAutoProxyRegistrar这个注册器在beanFactory准备阶段时注入了AnnotationAwareAspectJAutoProxyCreator(最终也是实现了BeanPostProcessor)这个类来作为aop的引擎
spring注册bean组件的几种方式:
1、@ComponentScan+@Component/@Controlle/@Service/@Repository
2、@Configuration + @Bean
3、@import
*直接import类
*import实现了ImportSelector接口的类
*import实现了ImportBeanDefinitionRegistrar接口的类
4、实现FactoryBean接口并用1方法注册,会生产程序员指定的bean实例