Spring IOC 容器預(yù)啟動流程源碼探析
在應(yīng)用程序中,一般是通過創(chuàng)建ClassPathXmlApplicationContext或AnnotationConfigApplicationContext這兩個最底層子類來啟動Spring IOC容器:
-
ClassPathXmlApplicationContext:xml文件配置版 -
AnnotationConfigApplicationContext: 注解版
由于當(dāng)下越來越流行基于Java注解的配置來創(chuàng)建我們的Bean,所以本文主要以注解版進(jìn)行探析。
AnnotationConfigApplicationContext的類關(guān)系結(jié)構(gòu)
我們先來看看我們探討的起點(diǎn)
public class Main {
public static void main(String[] args) {
new AnnotationConfigApplicationContext(Config.class);
}
@Configuration
public static class Config{
}
}
demo簡簡單單,那么,這里發(fā)生了什么?或許,我們可以先看看AnnotationConfigApplicationContext的類關(guān)系結(jié)構(gòu):

我們可以看到AnnotationConfigApplicationContext最上面有兩個頂級接口:
-
BeanFactory: Spring的核心接口,純粹的bean容器,主要定義了與Bean的相關(guān)方法 -
ResourceLoader:資源加載器,定義了getResource方法
繼承自三個父類:
-
DefaultResourceLoader: 默認(rèn)的資源加載器,實(shí)現(xiàn)了三種加載資源的方式通過
path加載資源通過
classpath加載資源通過
URL加載資源
-
AbstractApplicationContext: 實(shí)現(xiàn)了ApplicationContext接口的抽象類,主要功能實(shí)現(xiàn)了啟動IOC容器的核心方法:
refresh()發(fā)布事件
大量
getBean相關(guān)的操作, 主要通過抽象方法getBeanFactory基于子類實(shí)現(xiàn)大量留于子類擴(kuò)展的空方法
消息國際化
-
GenericApplicationContext:使用組合的方式引進(jìn)了最底層的
BeanFactory實(shí)現(xiàn)類:DefaultListableBeanFactory定義了
registerBean的相關(guān)操作,其實(shí)是通過DefaultListableBeanFactory實(shí)現(xiàn)的
不難發(fā)現(xiàn),
ApplicationContext名副其實(shí),確實(shí)就是一個應(yīng)用上下文,對于bean的相關(guān)操作,容器的管理,依舊是由我們的BeanFactory進(jìn)行實(shí)現(xiàn)。
準(zhǔn)備啟動
1. 創(chuàng)建我們的實(shí)例:AnnotationConfigApplicationContext
new AnnotationConfigApplicationContext(Config.class);
2.進(jìn)入到AnnotationConfigApplicationContext構(gòu)造方法
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
3. 調(diào)用我們的空構(gòu)造方法,這里要先實(shí)例化我們的父類
3.1 實(shí)例化DefaultResourceLoader
public DefaultResourceLoader() {
this.classLoader = ClassUtils.getDefaultClassLoader();
}
ClassUtils.getDefaultClassLoader()主要有兩步操作
//獲取線程上下文的類加載器
ClassLoader cl = = Thread.currentThread().getContextClassLoader();
if(cl == null) //為空則獲取系統(tǒng)的類加載器 即為應(yīng)用類加載器
cl = ClassLoader.getSystemClassLoader();
這里我們非Tomcat環(huán)境,所以返回的是AppClassLoader
3.2 實(shí)例化AbstractApplicationContext
//為BeanFactoryPostProcessor賦初始值
List<BeanFactoryPostProcessor> BeanFactoryPostProcessor = new ArrayList<>();
public AbstractApplicationContext() {
//引入一個資源解析器
this.resourcePatternResolver = getResourcePatternResolver();
}
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
3.3 實(shí)例化GenericApplicationContext
public GenericApplicationContext() {
//引入BeanFactory實(shí)現(xiàn)
this.beanFactory = new DefaultListableBeanFactory();
}
3.4 實(shí)例化自己
public AnnotationConfigApplicationContext() {
//初始化基于注解的bean定義掃描器
this.reader = new AnnotatedBeanDefinitionReader(this);
//初始化基于classpath的bean定義掃描器
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
3.4.1 AnnotatedBeanDefinitionReader初始化過程
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
//registry就是我們AnnotationConfigApplicationContext
this.registry = registry;
//引入條件表達(dá)式計算器 處理@Conditional注解
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
//注冊所有與注解相關(guān)的后置處理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
registerAnnotationConfigProcessors(registry, null)中主要做了以下幾件事情:
-
為
DefaultListableBeanFactory賦值了兩個引用//依賴排序器,用于處理添加了Priority、Order注解以及實(shí)現(xiàn)了Ordered接口的bean beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); //@Autowire候選解析器 beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); -
往容器中注冊了6個后置處理器的bean定義
注冊配置類的后置處理器
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME);注冊處理@Autowired注解的后置處理器
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME);注冊處理@Required注解的后置處理器(5.1版本開始已被廢棄)
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class); def.setSource(source); registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME);注冊處理JSR-250規(guī)范注解的后置處理器,@Resource,@PostConstruct,@PreDestroy
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class); def.setSource(source); registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME);注冊處理@EventListener注解的后置處理器
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME);注冊事件監(jiān)聽工廠,給上面的EventListenerMethodProcessors使用
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME);
3.4.2 ClassPathBeanDefinitionScanner初始化過程
經(jīng)歷了一系列的構(gòu)造器傳遞
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
this(registry, true);
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment) {
this(registry, useDefaultFilters, environment,
(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}
最終實(shí)現(xiàn)的構(gòu)造器方法
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
//默認(rèn)為true
if (useDefaultFilters) {
//注冊默認(rèn)的過濾器
registerDefaultFilters();
}
//設(shè)置環(huán)境
setEnvironment(environment);
//設(shè)置資源加載器
setResourceLoader(resourceLoader);
}
registerDefaultFilters方法
protected void registerDefaultFilters() {
//加入掃描@Component注解的過濾器,這樣就能掃到@Controller,@Service...
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
//JSR-250規(guī)范的注解
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
}
catch (ClassNotFoundException ex) {
}
try {
//JSR-330規(guī)范的注解
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
}
catch (ClassNotFoundException ex) {
}
}
4. 構(gòu)造方法執(zhí)行完畢,執(zhí)行register(annotatedClasses)方法,將配置類的bean定義注冊到容器中
public void register(Class<?>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
//這里就使用了剛剛初始化的AnnotatedBeanDefinitionReader掃碼器
//annotatedClasses即為在入口處傳進(jìn)的自定義配置類Config.class
this.reader.register(annotatedClasses);
}
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
//這里我們只傳了一個,只有一次循環(huán)
registerBean(annotatedClass);
}
}
public void registerBean(Class<?> annotatedClass) {
//spring的特點(diǎn),真正實(shí)現(xiàn)的都是do開頭的方法
doRegisterBean(annotatedClass, null, null, null);
}
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//將class封裝到bean定義中
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//由于配置類并未使用@Conditional注解,直接返回false
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
//解析bean定義的作用域
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//處理普通的bean定義注解,@Lazy @Primary @DependsOn @Role @Description
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//根據(jù)scopeMetadata中的proxy-mode屬性判斷是否需要進(jìn)行代理封裝,默認(rèn)否
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//將bean定義注冊到容器中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
前期準(zhǔn)備工作已基本完畢,可以開始調(diào)用
refresh方法啟動IOC容器了。
準(zhǔn)備花個30天時間,系統(tǒng)的來整理一下我對spring源碼的認(rèn)識:
Spring 源碼系列
- Spring源碼分析之 IOC 容器預(yù)啟動流程(已完結(jié))
- Spring源碼分析之BeanFactory體系結(jié)構(gòu)(已完結(jié))
- Spring源碼分析之BeanFactoryPostProcessor調(diào)用過程(已完結(jié))
- Spring源碼分析之Bean的創(chuàng)建過程
- Spring源碼分析之什么是循環(huán)依賴及解決方案
- Spring源碼分析之AOP從解析到調(diào)用
- Spring源碼分析之事務(wù)管理(上),事物管理是spring作為容器的一個特點(diǎn),總結(jié)一下他的基本實(shí)現(xiàn)與原理吧
- Spring源碼分析之事務(wù)管理(下) ,關(guān)于他的底層事物隔離與事物傳播原理,重點(diǎn)分析一下
Spring Mvc 源碼系列
- SpringMvc體系結(jié)構(gòu)
- SpringMvc源碼分析之Handler解析過程
- SpringMvc源碼分析之請求鏈過程
Mybatis 源碼系列
暫定
追更,可關(guān)注我的公眾號:奇客時間,分享純粹為了樂趣,也有一種成就感吧,筆者這篇文章先就到這