寫在前面
我對Spring原理的理解處於“點到為止”的狀態:對於主線流程不太重要的邏輯跳過,或者只關注它做了什麼。
學習Spring原始碼查詢了很多資料,分享幾篇大佬寫的文章,對我Spring的學習起到很大幫助
Spring IOC原始碼分析,是以ClassPathXmlApplicationContext為例
學習Spring原始碼建議搭建Spring-framemwork原始碼環境(這是一個比較麻煩的過程,可能遇到各種問題,需要有耐心..),新建個Module打斷點一步步除錯。
舉個例子,這是Spring的.class反編譯的結果,不但沒有註釋,可讀性也很差。
從細節來看不同ApplicationContext生命週期略有不同,以AnnotationConfigApplicationContext和ClassPathXmlApplicationContext為例,拋開Bean的解析邏輯,比如他們倆建立BeanFactory的時機也不一樣。
這篇文章我主要以spring-framework5.1.7的AnnotationConfigApplicationContext為例分析。
寫這篇文章花了很多時間,如有錯誤,還請批評指正。
分析Spring原始碼是一個漫長的過程,如果在某個節點卡住,不妨先放一放,過段時間回頭再看沒準會茅塞頓開。另外Spring某些知識點、特殊類都可以百度一下,這些知識點的集合構成了Spring原理。
Spring中的一些重要的類及概念
在解析原始碼之前,需要先弄清楚Spring中比較重要的類,在原始碼中可能經常遇到,如果不清楚是做什麼的會很懵,這塊有個大致印象即可。
ApplicationContext
ApplicationContext就是載入Spring容器的入口,Spring的一切從這裡開始。
基於載入配置方式的不同,常見的有:
AnnotationConfigApplicationContext
基於註解獲取配置也是本文會詳細說明的。
ClassPathXmlApplicationContext、FileSystemXmlApplicationContext
基於XML獲取配置,指定配置檔案路徑來獲取配置。
XmlWebApplicationContext
在SpringBoot以前,我們的Web應用要配置Spring,通常是在web.xml配置listener和applicationContext.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
複製程式碼
這時web應用依據載入web.xml的順序,ContextLoaderListener監聽到ServletContext載入事件,如果跟蹤原始碼最終預設會取到 Spring內建如下配置
為我們建立一個XmlWebApplicationContext例項。繼承結構
另外從繼承結構可以看出,Xml和Annotation在AbstractApplicationContext處開始是兩個分支,其實就是由於繼承結構的不同,在容器建立的一些節點上,執行的是同一個介面方法的不同例項方法,從而一些實現邏輯略有不同。這裡先有個大致印象就行。
BeanDefinition
就是用來描述Bean定義的類。在Java中每個類都有個Class物件,類似的,Spring中每個我們配置的Bean都有個BeanDefinition物件。 比如Bean對應的類、是否懶載入、作用域等都在這裡描述。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// ... 簡單擷取一部分
// 設定 Bean 的類名稱,將來是要通過反射來生成例項的
void setBeanClassName(@Nullable String beanClassName);
// 獲取 Bean 的類名稱
@Nullable
String getBeanClassName();
// scope
void setScope(@Nullable String scope);
// scope
@Nullable
String getScope();
// 懶載入
void setLazyInit(boolean lazyInit);
// 是否懶載入
boolean isLazyInit();
// depends-on="" 屬性設定的值。
// @DependsOn
void setDependsOn(@Nullable String... dependsOn);
// @DependsOn
@Nullable
String[] getDependsOn();
// 設定該 Bean 是否可以注入到其他 Bean 中,只對根據型別注入有效,
// 如果根據名稱注入,即使這邊設定了 false,也是可以的
void setAutowireCandidate(boolean autowireCandidate);
// 該 Bean 是否可以注入到其他 Bean 中
boolean isAutowireCandidate();
// @Primary
void setPrimary(boolean primary);
// 是否是 primary
boolean isPrimary();
// FactoryBean
void setFactoryBeanName(@Nullable String factoryBeanName);
// FactoryBean
@Nullable
String getFactoryBeanName();
// ... 後面太長就不寫了
}
複製程式碼
BeanFactory
BeanFactory就是生產Bean的工廠。BeanFactory的最終目的就是為我們產生Bean例項,只不過在產生Bean例項之前需要解析註解或XML,產生BeanDefinition並註冊到BeanFactory。我們常說的Spring容器中的Bean,一方面是指Bean例項,一方面也是指Bean定義,我覺得都不算錯。
Spring容器
上面提到BeanFactory,可能會聯想到Spring容器。
巨集觀上看,BeanFactory、ApplicationContext、包括後面會提到的DefaultListableBeanFactory、DefaultSingletonBeanRegistry,都可以算作Spring容器,或者他們的集合是Spring容器。這個容器一方面儲存了Bean例項,另一方面也儲存了Bean的定義。
微觀上看,容器是儲存我們Bean定義的是DefaultListableBeanFactory的一個map屬性、儲存Bean例項的是DefaultSingletonBeanRegistry的一個map屬性,都是map。
DefaultListableBeanFactory
我們具體操作的BeanFactory例項就是DefaultListableBeanFactory型別的。 這裡列出DefaultListableBeanFactory兩個重要的屬性,就是用來儲存BeanDefinition的容器。
// bean定義的對映,以name為key
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// bean定義名字List,以註冊順序排序
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
複製程式碼
FactoryBean
通過實現FactoryBean,會為我們例項化兩個Bean。
一個是當前Bean,只不過name前加了個&,標識出這個是FactoryBean的例項
一個是基於介面方法返回的例項來為我們建立Bean例項。
FactoryBean可以將一些複雜依賴的類合併成一個物件返回,可以用於封裝。
典型應用:mybatis的SqlSessionFactoryBean
使用示例:
@Component
public class MyFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
複製程式碼
public class User {
private String id;
private String name;
public User(){
id = "001";
name = "lby";
}
}
複製程式碼
功能驗證
public class SpringTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
User u = (User) context.getBean("myFactoryBean");
MyFactoryBean myFactoryBean = (MyFactoryBean) context.getBean("&myFactoryBean");
}
}
複製程式碼
輸出結果
BeanPostProcessor
後置處理器,他有兩個方法postProcessBeforeInitialization和postProcessAfterInitialization。
Bean在例項化之後、初始化前後會執行。
這只是個籠統的說法。所謂初始化就是呼叫Spring的InitMethods方法。
初始化Spring的Bean有三種方式:
init-method,可以在XML裡配置也可以在java config裡配置
實現InitializingBean介面
@PostConstruct註解,解析執行該註解的本身就是一個BeanPostProcessor,所以Spring的InitMethods不包括@PostConstruct
看過Bean的例項化部分的原始碼會發現,Bean在例項化之後這三種初始化方式的執行順序是
@PostConstruct -> InitializingBean -> init-method
解析@PostConstruct註解的是CommonAnnotationBeanPostProcessor後置處理器
而後置處理器是在InitMethods的前後執行。而InitMethods裡的執行順序是先執行InitializingBean後執行init-method,所以最終是這個執行順序。
不過按現在程式設計風格,一般都用@PostConstruct,另外兩個不常用
典型應用:CommonAnnotationBeanPostProcessor,就是解析@PostConstruct的後置處理器
使用示例:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("myDao".equals(beanName)) {
System.out.println("BeforeInitialization " + beanName + "...");
}
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("myDao".equals(beanName)) {
System.out.println("AfterInitialization " + beanName + "...");
}
return null;
}
}
複製程式碼
BeanFactoryPostProcessor
後置處理器,BeanFactoryPostProcessor可以在bean例項化之前可以讀取bean的定義並修改它。同時可以定義多個BeanFactoryPostProcessor,通過設定@Order來確定各個BeanFactoryPostProcessor執行順序
典型應用:ConfigrationClassPostProcessor,這是解析Bean的核心,後面會有解釋
使用示例
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory)
throws BeansException {
BeanDefinition bd = configurableListableBeanFactory.getBeanDefinition("myService");
bd.setBeanClassName("com.spring.bean.MyDao");
}
}
複製程式碼
這裡我們將myService的class由com.spring.bean.MyService改為com.spring.bean.MyDao,
public class SpringTest {
public static void main(String[] args){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext();
MyDao myDao = (MyDao)context.getBean("myDao");
MyDao myService = (MyDao)context.getBean("myService");
System.out.println(myService.toString());
}
}
複製程式碼
再將myService的例項輸出出來,結果已經變成com.spring.bean.MyDao的例項
BeanDefinitionRegistryPostProcessor
後置處理器,它繼承了BeanFactoryPostProcessor,可以認為是特別的BeanFactoryPostProcessor,通過實現BeanDefinitionRegistryPostProcessor可以介入容器的初始化過程,他的呼叫時機與BeanFactoryPostProcessor一樣,只不過優先於BeanFactoryPostProcessor呼叫。
典型應用:ConfigrationClassPostProcessor
使用示例:
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanDefinitionRegistryPostProcessor -> postProcessBeanFactory");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
String[] beanDefinitionNames = registry.getBeanDefinitionNames();
for (String name : beanDefinitionNames) {
System.out.println("MyBeanDefinitionRegistryPostProcessor -> " + name);
}
}
}
複製程式碼
可以看出BeanDefinitionRegistryPostProcessor要先於BeanFactoryPostProcessor執行,postProcessBeanDefinitionRegistry方法要先於postProcessBeanFactory執行。
至於為什麼是這個結果,如果看了原始碼,實際上Spring內部的呼叫順序就是這樣。
ConfigurationClassPostProcessor
它繼承了BeanDefinitionRegistryPostProcessor,所以他也是後置處理器。在Spring解析Bean的過程中,他是最重要的也是第一個執行的BeanFactoryPostProcessor,我們的自定義的@Compent、@Bean、@Import等都是由這個類開始解析並註冊的。
ImportSelector
是一個介面,功能上可以簡單把它理解為動態版的@Import
典型應用:@EnableTransactionManagement
使用示例:
public class MyImport {
public void printSomething() {
System.out.println("MyImport");
}
}
public class MyImportSelector implements ImportSelector {
public void printSomething(){
System.out.println("MyImportSelector");
}
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 當然這裡也可以依賴annotationMetadata的內容,執行一些特殊邏輯
// annotationMetadata可以獲得打上@Import類的後設資料資訊
return new String[]{MyImportSelectorAAA.class.getName(),
MyImportSelectorBBB.class.getName()};
}
}
public class MyImportSelectorAAA {
public void printSomething(){
System.out.println("MyImportSelectorAAA");
}
}
public class MyImportSelectorBBB {
public void printSomething(){
System.out.println("MyImportSelectorAAA");
}
}
複製程式碼
JavaConfig
@Configuration
@ComponentScan("com.lby")
@Import({MyImport.class, MyImportSelector.class})
public class AppConfig {
}
複製程式碼
功能驗證
public class SpringTest {
public static void main(String[] args){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyImport myImport = (MyImport)context.getBean(MyImport.class.getName());
myImport.printSomething();
MyImportSelectorAAA myImportSelectorAAA =
(MyImportSelectorAAA)context.getBean(MyImportSelectorAAA.class.getName());
myImportSelectorAAA.printSomething();
MyImportSelectorBBB myImportSelectorBBB =
(MyImportSelectorBBB)context.getBean(MyImportSelectorBBB.class.getName());
myImportSelectorBBB.printSomething();
}
}
複製程式碼
輸出結果
可以看到上面Imoprt的類已經成功被例項化。MyImport是普通類,MyImportSelector實現了ImportSelector介面,重寫selectImports方法返回MyImportSelectorAAA、MyImportSelectorBBB
@Import(MyImport.class)是直接將引入的MyImport註冊到BeanFactory
@Import(MyImportSelector.class)則是將MyImportSelectorAAA、MyImportSelectorBBB註冊到BeanFactory,但MyImportSelector本身不會註冊。
ImportBeanDefinitionResgistor
典型應用:@EnableAspectAutoProxy、@MapperScan
ApplicationContextAware
IOC容器的初始化
IOC容器的初始化我這裡粗略的分成三步走:
1、BeanFactory的準備工作
2、Bean的解析
3、Bean的例項化
這三步可以說一步比一步難,先有個心理準備。
BeanFactory的準備工作
從AnnotationConfigApplicationContext開始,走進SpringIOC容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
複製程式碼
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
// 構造方法
this();
// 註冊類,所謂註冊,把它理解為把這個bean放到容器裡即可
register(annotatedClasses);
// 重新整理容器的內容,核心方法
// 不論是AnnotationConfigApplicationContext還是ClassPathXmlApplicationContext都會走這同一個方法
refresh();
}
複製程式碼
我們先看構造方法,
public AnnotationConfigApplicationContext() {
// 重點,從類名字上可以看出是註解式bean定義讀取器
this.reader = new AnnotatedBeanDefinitionReader(this);
// 不是重點,忽略
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
複製程式碼
呼叫子類構造方法前會呼叫父類構造方法。AnnotationConfigApplicationContext繼承鏈路上有很多類,我們重點關注GenericApplicationContext的構造方法
public GenericApplicationContext() {
// 例項化了一個BeanFactory
this.beanFactory = new DefaultListableBeanFactory();
}
複製程式碼
可以看到AnnotationConfigApplicationContext的第一步就是通過構造方法為我們例項化一個空的BeanFactory即DefaultListableBeanFactory例項,我們常說的BeanFactory一般就是DefaultListableBeanFactory例項。
我們看一下DefaultListableBeanFactory的成員屬性
// 是否允許bean覆蓋
private boolean allowBeanDefinitionOverriding = true;
// 是否允許即使是懶載入的Bean立刻載入
private boolean allowEagerClassLoading = true;
// 比較器
@Nullable
private Comparator<Object> dependencyComparator;
// 用於檢查一個類定義是否有自動注入的解析器
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
// 依賴的類與例項的map對映
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);
// bean定義的對映,以name為key
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// 單例和非單例bean名稱對映,以型別為key
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
// 單例的bean名稱對映,以型別為key
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);
// bean定義名字List,以註冊順序排序
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
// 人工註冊的單例bean定義的有序Set,以註冊順序排序
private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);
// 快取bean定義名字的陣列
@Nullable
private volatile String[] frozenBeanDefinitionNames;
// 是否允許bean定義的後設資料被快取,以用於所有的bean
private volatile boolean configurationFrozen = false;
複製程式碼
可以說DefaultListableBeanFactory例項就是我們的BeanDefinition容器。更具體點就是beanDefinitionMap。
回到這裡
public AnnotationConfigApplicationContext() {
// 重點,從類名字上可以看出是註解式bean定義讀取器
this.reader = new AnnotatedBeanDefinitionReader(this);
// 不是重點,忽略
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
複製程式碼
呼叫父類的構造方法生成DefaultListableBeanFactory物件之後,重點就是
this.reader = new AnnotatedBeanDefinitionReader(this);
複製程式碼
順著呼叫鏈路一路下鑽,只挑重點,執行到了AnnotationConfigUtils類的registerAnnotationConfigProcessors方法
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
複製程式碼
這裡BeanDefinitionRegistry型別的registry就是我們的當前例項。前面通過構造方法例項化了GenericApplicationContext物件,而GenericApplicationContext實現了BeanDefinitionRegistry介面,相當於BeanDefinitionRegistry的子類。
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 不是重點
// 其實就是為我們返回當前GenericApplicationContext例項(registry)的DefaultListableBeanFactory型別beanFactory屬性
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {// 不是重點,前面剛例項化的DefaultListableBeanFactory,這裡必不為空
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
// 設定比較器,往後看就知道排序器是用來幹啥的了
// 其實這裡就算不初始化比較器也沒事,後面比較的地方也會有預設的比較器
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)){
// 設定自動注入的解析器
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// 註冊ConfigurationClassPostProcessor後置處理器
// ConfigurationClassPostProcessor是非常重要的類
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// 註冊AutowiredAnnotationBeanPostProcessor後置處理器
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// JSR-250一種規範,需要支援@Resource、@PostConstruct以及@PreDestroy註解
// CommonAnnotationBeanPostProcessor後置處理器就是處理這些註解的
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// JPA支援,註冊 PersistenceAnnotationProcessor後置處理器
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
...
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
// 註冊 EventListenerProcessor後置處理器
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
// 註冊 EventListenerFactory
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
複製程式碼
registerAnnotationConfigProcessors主要就是為我們註冊了一些Spring預設的後置處理器。這裡所謂的註冊,主要就是將這些後置處理器轉換成BeanDefinition物件,並存入前面我們例項化的Bean工廠中(DefaultListableBeanFactory物件的beanDefinitionMap、beanDefinitionNames屬性)。
此處註冊了這幾個後置處理器
ConfigurationClassPostProcessor
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
PersistenceAnnotationProcessor
EventListenerProcessor
EventListenerFactory
回到我們前面AnnotationConfigApplicationContext的構造方法
// AnnotationConfigApplicationContext類的AnnotationConfigApplicationContext(Class<?>... annotatedClasses)
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
// 構造方法
this();
// 註冊類,所謂註冊,把它理解為把這個bean放到容器裡即可
register(annotatedClasses);
// 重新整理,核心方法
// 不論是AnnotationConfigApplicationContext還是ClassPathXmlApplicationContext都會走這同一個方法
// AnnotationConfigApplicationContext繼承自GenericApplicationContext
// GenericApplicationContext只能refresh一次 否則會拋異常
refresh();
}
複製程式碼
無參構造方法this主要流程已經走完,register(annotatedClasses)其實就是把我們傳入的Bean,比如將我們的JavaConfig註冊到BeanFactory中而已。
至此,三步走中最簡單的一步:BeanFactory準備工作,大致流程已經走完。
總結下,核心邏輯就是為我們例項化BeanFactory,並將內建的幾個重要的後置處理器註冊到BeanFactory中。這裡算是個入門,重中之重是後面的refresh方法。
Bean的解析
檢視refresh方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 不是重點,容器重新整理前的準備工作,記錄下容器的啟動時間、標記“已啟動”狀態、close狀態等。
prepareRefresh();
// 獲取我們的beanFactory,這裡Annotation版和XML版是不同的實現
// Annotation版,因為我們在例項化AnnotationConfigApplicationContext時已經建立了beanFactory
// 所以這裡的輯僅僅是獲取而已
// 但如果是XML版,是在這個環節建立beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// BeanFactory的準備工作
// 主要是加了兩個後置處理器:ApplicationContextAwareProcessor,ApplicationListenerDetector
// 一些依賴的略,註冊一些內建bean等
// 注意這裡是新增後置處理器是add到BeanFactory(AbstractBeanFactory類的beanPostProcessors屬性)
// 而前面我們在例項化BeanFactory時是註冊了幾個後置處理器,將後置處理器轉換為BeanDefinition放入BeanFactory中
// 這裡沒必要太糾結
// 當前只是Spring將一分部後置處理器轉換成BeanDefine註冊到BeanFactory,一部分是直接add到BeanFactory
// 後面都會統一add到BeanFactory的beanPostProcessors屬性
prepareBeanFactory(beanFactory);
try {
// 這裡現在是空方法,實際上是提供給子類的擴充套件點,子類可以重寫該方法。
postProcessBeanFactory(beanFactory);
// 重點,執行BeanFactoryProcessor各個實現類的 postProcessBeanFactory方法
// 執行內建的和我們手動新增的BeanFactoryPostProcessors
// 手動新增的是需要手動呼叫annotationConfigApplicationContext.addBeanFactoryPostProcessor來新增
// 那內建的呢?回想我們前面BeanFactory初始化spring為我們加了很多後置處理器
// 其中ConfigurationClassPostProcessor就是繼承自BeanFactoryPostProcessor
// ConfigurationClassPostProcessor是重點!
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊 BeanPostProcessor 的實現類
// 所有的BeanPostProcessor統一add到BeanFactory的beanPostProcessors屬性,準備執行
registerBeanPostProcessors(beanFactory);
// 不是重點,忽略。
initMessageSource();
// 初始化當前 ApplicationContext 的事件廣播器
initApplicationEventMulticaster();
// 和上面postProcessBeanFactory類似,也是空方法,提供給子類的擴充套件點
onRefresh();
// 不是重點。註冊事件監聽器,監聽器需要實現 ApplicationListener 介面。
registerListeners();
// 重點,初始化所有的 singleton beans
finishBeanFactoryInitialization(beanFactory);
// 最後,廣播事件,ApplicationContext 初始化完成
finishRefresh();
}
catch (BeansException ex) {
...
}
finally {
...
}
}
}
複製程式碼
refresh是巨集觀上的處理流程,我們重點關注這幾個方法,其他的先忽略:
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
- invokeBeanFactoryPostProcessors(beanFactory);
- registerBeanPostProcessors
- finishBeanFactoryInitialization(beanFactory);
這裡我們劃分一下,前兩個方法屬於Bean的解析過程,後兩個方法屬於Bean的例項化過程。
obtainFreshBeanFactory()
順著呼叫鏈路會執行到AbstractApplicationContext類的refreshBeanFactory方法。
refreshBeanFactory是抽象方法,不同的例項執行不同的實現。回頭看上面ApplicationContext的繼承結構, 因為我們的AnnotationConfigApplicationContext是GenericApplicationContext的子類,所以應該走GenericApplicationContext類的refreshBeanFactory方法,他的邏輯比較簡單,就是獲取前面BeanFactory準備工作例項化的DefaultListableBeanFactory例項。
而如果是ClassPathXmlApplicationContext,會執行AbstractRefreshableApplicationContext的refreshBeanFactory方法,它的DefaultListableBeanFactory例項是在這裡建立的,這裡就不詳細闡述了。而這也是Annotation和XML區別之一。
invokeBeanFactoryPostProcessors(beanFactory)
只看主線,順著呼叫鏈路會執行到如下方法
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 一個用於判斷的容器而已,凡是已經執行過的後置處理器都放入這裡
Set<String> processedBeans = new HashSet<>();
// 我們的BeanFactory實際是DefaultListableBeanFactory例項
// 而DefaultListableBeanFactory實現了BeanDefinitionRgistry,所以是True
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 用來存放BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 用來存放BeanDefinitionRegistryPostProcessor
// BeanDefinitionRegistryPostProcessor繼承了用來存放BeanFatoryPostProcessor
// 這兩個集合就是做了個區分,後面邏輯需要
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 為我們手動新增的beanFactoryPostProcessors做區分存入上面兩個集合裡
// 除了用註解,我們可以這麼新增BeanFactoryPostProcessor
// context.addBeanFactoryPostProcessor(newMyBeanDefinitionRegistryPostProcessor());
// 不過此處一般情況下為空,我覺得可以跳過
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// 就是個臨時變數而已,後面的邏輯共用這個變數
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 下面方法過長,我們劃分一下
// 從這開始算是第一步,執行實現了PriorityOrdered介面的BeanDefinitionRegistrPostProcessor
// 首先,呼叫實現PriorityOrdered的BeanDefinitionRegistryPostProcessors
// PriorityOrdered即優先排序,是個介面,繼承自Ordered介面
// 而ConfigurationClassPostProcessor實現了PriortyOrdered介面
// Ordered介面就是返回數量而已,用於排序,從而影響後置處理器的執行順序,其實我們理解為一個標記介面即可
// 就是從我們的beanFactory的beanDefinitionNames中找到型別是BeanDefinitionRegistryPostProcessor的後置處器
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 當前postProcessorNames中只有ConfigurationClassPostProcessor
// 因為前面註冊的幾個後置處理器只有ConfigurationClassPostProcessor是BeanDefinitionRegistryPostProcesor
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 返回一個ConfigurationClassPostProcessor例項放入currentRegistryProcessors中
// beanFactory.getBean為我們返回例項,是個很重要的方法,這個之後詳說
// 這裡看到在真正給所有的Bean例項化前,實際上已經有Spring內建處理器先例項化了
currentRegistryProcessors.add(
beanFactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 不是重點,可以跳過
// 就是給currentRegistryProcessors排序當前我們這裡只有一個ConfigurationClassPostProcessor例項
// 其實裡面的實現很簡單,就是基於order的值排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// BeanDefinitionRegistryPostProcessors的實現都放這裡
registryProcessors.addAll(currentRegistryProcessors);
// 執行ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 清空
currentRegistryProcessors.clear();
// 從這裡算是第二步,執行實現了Ordered介面且前面未執行過的BeanDefinitionRegistryPostProcessor
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 再次從我們的beanFactory的beanDefinitionNames中找到型別是BeanDefinitionRegistryPostProcessor的後置處器
// 又獲取一次,前面其實剛獲取到一次,引數一模一樣,之所以又取出一遍,因為前面執行過後置處理器,可能有變動
postProcessorNames = beanFactory.
getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true,false);
for (String ppName : postProcessorNames) {
// 獲取未處理的且實現Ordered介面的後置處理器
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(
beanFactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
// BeanDefinitionRegistryPostProcessor的實現都放入registryProcessors
registryProcessors.addAll(currentRegistryProcessors);
// 執行我們自定義的BeanDefinitionRegistryPostProcessor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 清空
currentRegistryProcessors.clear();
// 這裡算第三步,執行剩餘的BeanDefinitionRegistryPostProcessor
// 也就是沒有實現Ordered介面的BeanDefinitinRegistryPostProcessor
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 最後,呼叫所有其他BeanDefinitionRegistryPostProcessors
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(
beanFactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 現在,呼叫到目前為止處理的所有處理器的postProcessBeanFactory回撥
// 就是執行BeanFactoryPostProcessors的回撥方法,前面都是執行BeanDefinitionRegistryPostProcessor的回撥
// 到這其實就能明白前面為什麼要區分registryProcessors,regularPostProcessors
// 其實就是做了一個區分而已,然後統一呼叫postProcessBeanFactory回撥
// regularPostProcessor表示未繼承BeanDefinitionRegistryPostProcessor
// registryProcessors表示繼承了BeanDefinitionRegistryPostProcessor,只有我們自定義add的這裡才會有
// 前面幾個步驟只執行了BeanDefinitionRegistryPostProcessor的回撥
// 但還沒有執行BeanFactoryPostProcessor的回撥,此處執行
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else { // 跳過吧,不確定什麼情況會走這條線
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 前面取的是實現BeanDefinitionRegistryPostProcessor的後置處理器,這裡獲取實現BeanFactoryPostProcessor的後處理器
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 以下3個List用於區分而已:實現PriorityOrdered的、實現Ordered、未實現的後置處理器
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
// 前面執行過的跳過
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 這裡跟前面處理BeanDefinitionRegistryPostProcessor類似也分三步走
// 第一步執行實現PriorityOrdered的
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 第二步執行實現Ordered
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 第三步執行未排序的
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
// 存疑
beanFactory.clearMetadataCache();
}
複製程式碼
invokeBeanFactoryPostProcessors這個方法雖然很長,但沉下心來慢慢看,其實很簡單,而且執行步驟相似。
總結下該方法做的事情,就是回撥BeanFactoryPostProcessors、BeanDefinitionRegistryPostProcessor,也就是我們前面提到的其中兩個後置處理器。只不過這些後置處理器的執行順序有個規則:
1、先執行實現PriorityOrdered介面的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,其實只有ConfigurationClassPostProcessor,這也是非常重要的類,可以說他是開始解析Bean的入口,ConfigurationClassPostProcessor會掃描Bean並解析註冊到BeanFactory
2、執行實現Ordered介面的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
3、執行剩餘的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
4、執行實現PriorityOrdered介面的BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor的postProcessBeanFactory方法
5、執行實現Ordered介面的BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor的postProcessBeanFactory方法
6、執行剩餘的BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor的postProcessBeanFactory方法
後續的解析邏輯實際上就是基於這幾個後置處理器是怎麼解析的。我們主要分析ConfigurationClassPostProcessor。
ConfigurationClassPostProcessor
前面我們分析過BeanDefinitionRegistryPostProcessor的執行順序,ConfigurationClassPostProcessor實現了BeanDefinitionRegistryPostProcessor,是第一個被執行的後置處理器,他重寫了兩個方法postProcessBeanDefinitionRegistry和postProcessBeanFactory。
按照我們前面分析的執行過程,ConfigurationClassPostProcessor作為BeanDefinitionRegistryPostProcessor的子類先執行法postProcessBeanDefinitionRegistry方法,當所有的法postProcessBeanDefinitionRegistry方法執行完畢之後,ConfigurationClassPostProcessor作為BeanFactoryPostProcessor的子類執行postProcessBeanFactory方法。
我們先看postProcessBeanDefinitionRegistry方法,順著主線呼叫鏈路找到如下方法processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 獲得所有的BeanDefine,也就是前面註冊的那幾個後置處理器,我們前面把後置處理器轉換成BeanDefinition註冊到了eanFactory中
// 加上我們自己註冊的配置Bean:AppConfig
// 前面在refresh之前,我們把AppConfig.class註冊到了BeanFactory中
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 判斷beanDef是Full還是Lite
// 所謂Full 就是用@Configuration註解修飾
// 所謂Lite 就是用@Component、@ComponentScan、@Import、@ImportResource其中之一修飾
// 下面是判斷“CONFIGURATION_CLASS_ATTRIBUTE”屬性值是Full還是Lite
// 初次執行時CONFIGURATION_CLASS_ATTRIBUE為null,所以不走下面邏輯
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
// 列印debug日誌而已
...
}
// 預設會走這裡,檢查beanDef的註解,將他歸類為Full或Lite
// 設定“CONFIGURATION_CLASS_ATTRIBUTE”屬性,標識它是Full還是Lite
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)){
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
// 檢測通過封閉的應用程式上下文提供的任何自定義bean名稱生成策略
SingletonBeanRegistry sbr = null;
// registry實際上就是DefaultListableBeanFactory物件
// DefaultListableBeanFactory的繼承鏈路上既有SingletonBeaRegistry,也有BeanDefinitionRegistry
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
// 從命名看來是Bean命名生成器,預設也不會走,忽略吧
...
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// candidates是所有configBean
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 解析configBean,解析了config上個各類註解,掃描其他bean並註冊到BeanFactory
// 如果是@Compent註解會直接解析並註冊到BeanFactory
// 如果是@Import @Bean等註解會先放入parser的ConfigurationClass,後面單獨處理
// 其中如果是@Import的類實現了ImportBeanDefinitionRegistrars
// 會放到configClass的ImportBeanDefinitionReistrars
// 這裡只是Spring做了個區分,後面處理邏輯會區別對待處理而已
parser.parse(candidates);
parser.validate();
//上面parse裡解析@Import、@Bean最後都放入ConfigurationClass,這裡取出來
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 這裡是將前面只解析但沒註冊的Bean,都註冊
// 比如@Import、@Bean、@ImportResources
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
// 在解析的過程中會發現新的Bean並註冊到BeanFactory中
// 這裡用於做迴圈判斷,讓新註冊的Bean也會解析到
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.
checkConfigurationClassCandidate(bd, this.metadataReaderFactory)&&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
// 註冊一個ImportStack例項 以支援ImportAware @Configuration類,存疑
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
...
}
複製程式碼
這個方法我們主要關注幾點:
1、首先找到當前容器的所有BeanDefinition,預設情況下只有我們自己加入的JavaConfig和Spring自己註冊的後置處理器。
2、遍歷這些BeanDefinition,找到我們配置的Bean:@Configuration、@Component、@ComponentScan、@Import、@ImportResource等修飾的Bean,作為我們配置類,也是後面解析的入口,一般情況下只有我們自己註冊的JavaConfig。
這裡將配置類分成兩種:Full和Lite
所謂Full 就是用@Configuration註解修飾的類
所謂Lite 就是用@Component、@ComponentScan、@Import、@ImportResource其中之一修飾
Full和Lite的區別後面會有解釋,這裡只是做了個區分。
3、解析Bean
parser.parse(candidates);
複製程式碼
順著主線呼叫鏈路,執行到了doProcessConfigurationClass
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
// 首先遞迴處理(巢狀)類,先忽略吧
processMemberClasses(configClass, sourceClass);
}
// Process any @PropertySource annotations
// 處理@PropertySource註解,應用上可以把配置檔案的值直接注入到bean屬性,暫時先忽略
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
...
}
// Process any @ComponentScan annotations
// 處理@ComponentScan註解
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
// 如果沒有@ComponentScan,或者@Condition條件跳過,就不再進入這個if
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// config類使用@ComponentScan註釋 - >立即執行掃描 返回掃描到的BeanDefinitionHolder
// 返回的就是我們加@Compent等註解的BeanDefinitionHolder
// BeanDefinitionHolder就是BeanDefinition+nam的封裝
// parse下面的方法暫時先不分析了,大致看了下就是基於註解轉換成BeanDefinition
// 並註冊到BeanFactory,最後為我們返回解析到的Bean集合
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively ifneeded
// 檢查任何進一步配置類的掃描定義集,並在需要時遞迴解析
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
// checkConfigurationClassCandidate方法前面遇到過
// 檢查bdCand的註解,將他歸類為Full或Lite,並設定“CONFIGURATION_CLASS_ATTRIBUTE”屬性
// 用來標識它是Full還是Lite
// 也就是判斷掃描到的類中是否還有配置類(比如配置多資料來源),如果有遞迴解析,這個我們也忽略吧
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand,this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
// @Import註解是spring中很重要的一個註解,Springboot大量應用這個註解
// @Import三種類,普通類,ImportSelector,ImportBeanDefinitionRegistrar
// 存疑
processImports(configClass, sourceClass, getImports(sourceClass), true);
// Process any @ImportResource annotations
// 先忽略,@ImportResource處理xml配置
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
...
}
// Process individual @Bean methods
// 找到@Bean修飾的方法,add到configClass
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
// 先忽略,預設沒走 存疑
processInterfaces(configClass, sourceClass);
// Process superclass, if any
// // 先忽略,預設沒走 存疑
if (sourceClass.getMetadata().hasSuperClass()) {
...
}
// No superclass -> processing is complete
return null;
}
複製程式碼
這裡巨集觀上的解析邏輯,按不同註解分別解析了@ComponentScan、@Import、@Bean等註解
- 先解析處理@PropertySource註解,就是我們常用的讀取配置檔案
- 處理@ComponentScan註解
- 處理@Import註解
Import裡面又分三種情況,普通Import、ImportSelector、ImportBeanDefinitionRegistrar
- 處理@ImportResource
- 處理@Bean修飾的方法
具體的解析邏輯還需要下鑽逐步分析...,這裡我就不扯了,也扯不明白...,到processConfigBeanDefinitions執行結束為止,大體意思應該就是掃描到的Bean轉換成BeanDefinition並註冊到BeanFactory中。
按照前面的執行規則,之後會執行ConfigurationClassPostProcessor作為BeanFactoryPostProcessor的子類的postProcessBeanFactory方法,我們主要關注如下部分
// config cglic動態代理
enhanceConfigurationClasses(beanFactory);
// 新增一個後置處理器ImportAwareBeanPostProcessor
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
複製程式碼
前面我們的JavaConfig區分了Full和Lite,這裡就是針對Full做了處理。如果Bean是Full型別,會使用cglib動態代理重新生成JavaConfig的代理類的物件,程式碼就不分析了,也分析不明白。。。,我們直接看結果
在執行cglib動態代理之前,beanDefinition的beanClass屬性還是屬於AppConfig型別 在cglib動態代理之後,beanClass就變為代理類至於這裡為什麼要針對Full型別的Bean也就是@Configuration修飾的JavaConfig要使用cglib動態代理,我瞭解到的造成的影響之一是:cglib動態代理可以防止JavaConfig中的Bean重複被例項化。
我們的第二步:Bean的解析,到這裡算是結束。總結下,核心類是ConfigurationClassPostProcessor,這個後置處理器為我們解析了Bean,實際的解析邏輯我也是似懂非懂,即便如此也能大致瞭解Bean的解析過程以及Full型別的bean是使用cglib動態代理等實現。到此為止,我們定義的Bean還沒有例項化,只是被解析成BeanDefinition儲存在BeanFactory中。
Bean的例項化
前面的流程已經將Bean解析,轉換成BeanDefine並註冊到了BeanFactory
回到refresh方法,例項化過程主要依賴這兩個方法
// 註冊 BeanPostProcessor 的實現類
// 所有的BeanPostProcessor統一add到BeanFactory的beanPostProcessors屬性,準備執行
registerBeanPostProcessors(beanFactory);
// 重點,初始化所有的 singleton beans
finishBeanFactoryInitialization(beanFactory);
複製程式碼
registerBeanPostProcessors
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 找到所有已經註冊到BeanFactory的BeanPostProcessor
// 除了我們自己加的,還有Spring前面內建的兩個
// AutowiredAnnotationProcessor
// CommonAnnotationProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 新增BeanPostProcessorChecker後置處理器
// 後置處理器總數就是 前面add的後置處理器 + 1 + 註冊的BeanPostProcessor
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 如果熟悉前面BeanFactoryPostProcessor的邏輯,這裡一看就懂,跟前面很相似
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 說一下BeanPostProcessor的註冊,前面的某些環節會加一些BeanPostProcessors
// 有的是註冊在BeanFactory
// 有的是直接add到AbstractBeanFactory的beanPostProcessors屬性
// 而這裡就是將註冊在BeanFactory裡的add到AbstractBeanFactory的beanPostProcessors
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 又加了個後置處理器ApplicationListenerDetector
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
複製程式碼
這個方法很簡單,前面我們分析過BeanFactoryPostProcessor的執行順序,這倆類似,只不過這裡僅僅是先註冊而已。
finishBeanFactoryInitialization
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 字母意思是如果有這個conversionService,就set值,存疑,預設沒走先忽略吧
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// 忽略
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 如果有LoadTimeWeaverAware,先例項化,忽略
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 例項化所有非延遲載入的單例,重點
beanFactory.preInstantiateSingletons();
}
複製程式碼
後面的呼叫鏈路如下
preInstantiateSingletons->getBean->doGetBean
重點關注doGetBean
doGetBean裡首先獲得beanDefinition的class物件,取到其構造方法,然後根據構造方法例項化物件。
然後執行
...
populateBean(beanName, mbd, instanceWrapper);// Bean屬性值的注入 @Autowired
exposedObject = initializeBean(beanName, exposedObject, mbd);// 執行初始化方法
...
複製程式碼
initializeBean
就是執行初始化方法
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 執行一些aware回撥
// 如果Bean實現了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware這些介面則執行
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
// 先執行beanPostProcessor的postProcessBeforeInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {// 執行初始化方法 InitializingBean 和 init-method
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// 初始化方法執行完畢後,執行beanPostProcessor的postProcessAfterInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
複製程式碼
initializeBean就決定了我們Bean的幾個初始化方法的執行順序
BeanPostProcessor -> InitializingBean -> init-method
至此bean建立完畢。這只是最常見且最簡單的一條線路。
這裡面還有很多邏輯沒有解釋,比如屬性的注入、迴圈引用等等,等有機會再補充吧
文章比較長,不定時修整、更新一下~