Spring IOC 容器預啟動流程原始碼探析
在應用程式中,一般是通過創建ClassPathXmlApplicationContext或AnnotationConfigApplicationContext這兩個最底層子類來啟動Spring IOC容器:
ClassPathXmlApplicationContext:xml檔案配置版AnnotationConfigApplicationContext: 注解版
由于當下越來越流行基于Java注解的配置來創建我們的Bean,所以本文主要以注解版進行探析,
AnnotationConfigApplicationContext的類關系結構
我們先來看看我們探討的起點
public class Main {
public static void main(String[] args) {
new AnnotationConfigApplicationContext(Config.class);
}
@Configuration
public static class Config{
}
}
demo簡簡單單,那么,這里發生了什么?或許,我們可以先看看AnnotationConfigApplicationContext的類關系結構:

我們可以看到AnnotationConfigApplicationContext最上面有兩個頂級介面:
BeanFactory: Spring的核心介面,純粹的bean容器,主要定義了與Bean的相關方法ResourceLoader:資源加載器,定義了getResource方法
繼承自三個父類:
-
DefaultResourceLoader: 默認的資源加載器,實作了三種加載資源的方式-
通過
path加載資源 -
通過
classpath加載資源 -
通過
URL加載資源
-
-
AbstractApplicationContext: 實作了ApplicationContext介面的抽象類,主要功能-
實作了啟動IOC容器的核心方法:
refresh() -
發布事件
-
大量
getBean相關的操作, 主要通過抽象方法getBeanFactory基于子類實作 -
大量留于子類擴展的空方法
-
訊息國際化
-
-
GenericApplicationContext:-
使用組合的方式引進了最底層的
BeanFactory實作類:DefaultListableBeanFactory -
定義了
registerBean的相關操作,其實是通過DefaultListableBeanFactory實作的
-
不難發現,
ApplicationContext名副其實,確實就是一個應用背景關系,對于bean的相關操作,容器的管理,依舊是由我們的BeanFactory進行實作,
準備啟動
1. 創建我們的實體:AnnotationConfigApplicationContext
new AnnotationConfigApplicationContext(Config.class);
2.進入到AnnotationConfigApplicationContext構造方法
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
3. 呼叫我們的空構造方法,這里要先實體化我們的父類
3.1 實體化DefaultResourceLoader
public DefaultResourceLoader() {
this.classLoader = ClassUtils.getDefaultClassLoader();
}
ClassUtils.getDefaultClassLoader()主要有兩步操作
//獲取執行緒背景關系的類加載器
ClassLoader cl = = Thread.currentThread().getContextClassLoader();
if(cl == null) //為空則獲取系統的類加載器 即為應用類加載器
cl = ClassLoader.getSystemClassLoader();
這里我們非Tomcat環境,所以回傳的是AppClassLoader
3.2 實體化AbstractApplicationContext
//為BeanFactoryPostProcessor賦初始值
List<BeanFactoryPostProcessor> BeanFactoryPostProcessor = new ArrayList<>();
public AbstractApplicationContext() {
//引入一個資源決議器
this.resourcePatternResolver = getResourcePatternResolver();
}
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
3.3 實體化GenericApplicationContext
public GenericApplicationContext() {
//引入BeanFactory實作
this.beanFactory = new DefaultListableBeanFactory();
}
3.4 實體化自己
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;
//引入條件運算式計算器 處理@Conditional注解
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
//注冊所有與注解相關的后置處理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
registerAnnotationConfigProcessors(registry, null)中主要做了以下幾件事情:
-
為
DefaultListableBeanFactory賦值了兩個參考//依賴排序器,用于處理添加了Priority、Order注解以及實作了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規范注解的后置處理器,@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);注冊事件監聽工廠,給上面的EventListenerMethodProcessors使用
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME);
3.4.2 ClassPathBeanDefinitionScanner初始化程序
經歷了一系列的構造器傳遞
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));
}
最終實作的構造器方法
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
//默認為true
if (useDefaultFilters) {
//注冊默認的過濾器
registerDefaultFilters();
}
//設定環境
setEnvironment(environment);
//設定資源加載器
setResourceLoader(resourceLoader);
}
registerDefaultFilters方法
protected void registerDefaultFilters() {
//加入掃描@Component注解的過濾器,這樣就能掃到@Controller,@Service...
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
//JSR-250規范的注解
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
}
catch (ClassNotFoundException ex) {
}
try {
//JSR-330規范的注解
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
}
catch (ClassNotFoundException ex) {
}
}
4. 構造方法執行完畢,執行register(annotatedClasses)方法,將配置類的bean定義注冊到容器中
public void register(Class<?>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
//這里就使用了剛剛初始化的AnnotatedBeanDefinitionReader掃碼器
//annotatedClasses即為在入口處傳進的自定義配置類Config.class
this.reader.register(annotatedClasses);
}
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
//這里我們只傳了一個,只有一次回圈
registerBean(annotatedClass);
}
}
public void registerBean(Class<?> annotatedClass) {
//spring的特點,真正實作的都是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 = https://www.cnblogs.com/tomakemyself/p/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);
//根據scopeMetadata中的proxy-mode屬性判斷是否需要進行代理封裝,默認否
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//將bean定義注冊到容器中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
前期準備作業已基本完畢,可以開始呼叫
refresh方法啟動IOC容器了,
準備花個30天時間,系統的來整理一下我對spring原始碼的認識:
Spring 原始碼系列
- Spring原始碼分析之 IOC 容器預啟動流程(已完結)
- Spring原始碼分析之BeanFactory體系結構(已完結)
- Spring原始碼分析之BeanFactoryPostProcessor呼叫程序(已完結)
- Spring原始碼分析之Bean的創建程序
- Spring原始碼分析之什么是回圈依賴及解決方案
- Spring原始碼分析之AOP從決議到呼叫
- Spring原始碼分析之事務管理(上),事物管理是spring作為容器的一個特點,總結一下他的基本實作與原理吧
- Spring原始碼分析之事務管理(下) ,關于他的底層事物隔離與事物傳播原理,重點分析一下
Spring Mvc 原始碼系列
- SpringMvc體系結構
- SpringMvc原始碼分析之Handler決議程序
- SpringMvc原始碼分析之請求鏈程序
Mybatis 原始碼系列
暫定
追更,可關注我的公眾號:奇客時間,分享純粹為了樂趣,也有一種成就感吧,筆者這篇文章先就到這
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/169235.html
標籤:Java
上一篇:Springcloud技術分享
下一篇:中美日印程式員收入對比
