Spring原始碼閱讀 - 基礎流程
1. AnnotationConfigApplicationContext 的 reader 和 scanner
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
// 註冊解析這個 Bean 為 BeanDefinition
register(componentClasses);
// 重新整理容器,這個時候才是對這個 BeanDefinition 進行進一步解析
refresh();
}
public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }
內部邏輯先暫略,簡略描述
/** * 註解 Class 讀取器/處理器,在建構函式中建立 * AnnotatedBeanDefinitionReader 被例項化時已經向容器注入了部分 BeanDefinition * 區分 BeanPostProcessor 和 BeanFactoryPostProcessor * * 從其提供的 API 來看,大致就是將一個 Class 解析為 BeanDefinition 放入 BeanFactory */ private final AnnotatedBeanDefinitionReader reader; /** * 類路徑掃描器,可以進行包掃描,然後呢? * 這個在例項化時就沒有建立預先注入 BeanDefinition 了 */ private final ClassPathBeanDefinitionScanner scanner;
2. register
利用 reader 解析傳入的 Class 並進行基礎的解析轉換為 BeanDefinition
並將這個 BeanDefinition
注入 BeanFactory
org.springframework.context.annotation.AnnotationConfigApplicationContext#register
public void register(Class<?>... componentClasses) { Assert.notEmpty(componentClasses, "At least one component class must be specified"); // 使用註解BD讀取器去註冊/處理這個 Bean this.reader.register(componentClasses); }
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#register
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
// Generic [dʒəˈnerɪk],通用的,adj. (藥物或商品)無專利的,未註冊的
// 這個應該是用於封裝一個(可能)使用了註解的Bean,內部會進行解析註解資訊並封裝
// 封裝為 BeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
// 這個應該是涉及到條件注入等的
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
// 下面解析註解並設定 BeanDefinition,從上面的 new AnnotatedGenericBeanDefinition 可以看到只是將解析的註解封裝為一個屬性,具體
// 如何處理這些註解並設定 BeanDefinition 則由後面的進行解析
// 這個是不由 Spring 例項化,表示由這個 supplier 進行例項化,在哪裡有使用呢?
abd.setInstanceSupplier(supplier);
// 解析 Bean 的生命週期 Scope,這裡解析器也有幾種,Spring 自己的註解 @Scope 解析,javax.inject.Scope 的解析,略後者
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// beanName 生成,如何自定義 BeanName 生成器?
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 通用註解解析,那麼區分需要外部處理的和需要工具類處理的標準/條件是什麼?是是否可以直接進行簡單處理嗎(如上面的還需要解析器啥的)
// @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));
}
}
}
// 定製處理,customizers 這種可以定製處理的(或命名)的在 Spring 中還挺多的
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
// 問題:這裡的 beanName 為什麼不可以設計到 BeanDefinition 裡面呢,還需要封裝一層
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 如果當前類要被代理,代理的模式(JDK、CGLIB)
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 註冊 BD 到容器,沒有進一步處理
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
3. rerfresh.BeanFactoryPostProcessor 執行
上面已經將配置類給轉換為 BeanDefinition 注入容器了,接下來還需要解析這個 BeanDefinition
BeanFactoryPostProcessor:對 BeanDefinition 進行進一步修飾和處理,一般不會再將 BeanDefinition 注入 BeanFactory
BeanDefinitionRegistryPostProcessors:BeanFactoryPostProcessor 的子介面,主要是發現 BeanDefinition 並將 BeanDefinition 注入 BeanFactory
注意上面兩個介面所提供的/需要實現的方法的功能,一般不會在 BeanFactoryPostProcessor 介面提供的功能中發現 BD 和注入 BD
org.springframework.context.support.AbstractApplicationContext#refresh
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
// 暫略
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 暫略
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 內部設定了一些 BeanFactory 的屬性,直接注入了一些 Bean 例項
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 暫略,這裡好像 Web 進行處理了
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
// 呼叫 BeanFactoryPostProcessor 對 BeanDefinition 進行處理,通過對 BeanDefinition 處理可能又會發現更多的 BeanDefinition(如解析 @ComponentScan 時)
invokeBeanFactoryPostProcessors(beanFactory);
...
}
}
}
上面程式碼很多都略去了,現在僅先抓住主幹,具體細節暫略
org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 這種使用 Delegate 進行處理的方法, 是為了避免單個類太長 + 功能太多嗎?單一職責?有時候一些類我會命名為 Helper
// 注意這裡的 getBeanFactoryPostProcessors, 也就是我們也可以在 refresh 容器前將自定義的 BeanFactoryPostProcess add 進入 ApplicationContext
// 至於容器內部自己註冊進去的那些,會在內部自己發現(因為可以從傳入的 BeanFactory 中查)
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
// 這裡也暫略
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
下面這個也只是大體流程,具體的 BeanFactoryPostProcessor 沒有具體解析流程
org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
// 下面先呼叫的是 BeanDefinitionRegistryPostProcessors,這個主要是發現 BeanDefinition 並將 BeanDefinition 注入 BeanFactory
// 而與其類似的(其父介面)為 BeanFactoryPostProcessor,這個主要是對 BeanDefinition 進行進一步修飾和處理,一般不會再將 BeanDefinition 注入 BeanFactory
Set<String> processedBeans = new HashSet<>();
// 這個不是 BeanFactory 繼承鏈的,而是單獨的一個介面,提供對容器 BeanDefinition 的增刪查等操作
// 會有不是的場景嗎,後面不是就直接呼叫 BeanFactoryPostProcessor 操作 BeanDefinition 了(也即不能增刪等操作,僅能查詢並修改 BeanDefinition)
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 注意這裡就已經執行了,但是 BeanFactoryPostProcessor 介面的方法還未執行(父介面就是 BeanFactoryPostProcessor)
// 這裡實際上就可以執行以下自己的 BeanDefinition 發現邏輯啊等等,MyBatis 實現了這個嗎?
registryProcessor.postProcessBeanDefinitionRegistry(registry);
// 儲存的實際是一已執行的,這種命名是否可以優化一下便於閱讀
registryProcessors.add(registryProcessor);
}
else {
// BeanFactoryPostProcessor 型別,還未執行
regularPostProcessors.add(postProcessor);
}
}
// 注意下面執行 BeanFactory 內的 BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor,因為需要例項化才能執行,所以在這裡就 getBean 了
// 包括如果我們也注入了這些型別的,那麼也是在這裡就被 getBean 了,還可能沒經過整個生命週期,因此編寫時要注意
// 下面就是處理 BeanFactory 中的,內含
// 1. 上面自定義執行後注入的
// 2. Spring 容器內部自己注入的
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 先處理 PriorityOrdered 介面的,也先執行
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 處理 Ordered 介面的
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 處理其他的,內部進行了 while 處理,也即在上面執行後注入的如果未執行也會在下面執行,當然在下面執行後注入的也會被執行
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, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 這裡就是執行 BeanFactoryPostProcessor 介面的,優先順序也是先執行 BeanDefinitionRegistryPostProcessor 的,順序也是上面執行的順序
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 這裡引數傳入的優先順序反而靠後了
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
// 注意了,這裡僅執行了引數傳入的,對於 BeanFactory 內部的沒有執行
// 當然同時由於 BeanFactory 型別的原因,認為是不可以向內注入 BeanDefinition 的,因此也沒必要 while 關心是否有新的注入
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 下面就應該處理 BeanFactory 內部的 BeanFactoryPostProcessor 介面方法了,上面雖然執行了一些,但那是 BeanDefinitionRegistryPostProcessor 型別的(BeanFactoryPostProcessor 子介面)
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 獲取 BeanFactory 內部所有的 BeanFactoryPostProcessor,注意入參傳入的沒有
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
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
}
// 分類且按照順序執行
// 問題: 為什麼僅 priority 的在這裡就獲取了 Bean,而其他的後面才獲取呢(倒不是邏輯問題,而是寫的時候怎麼想的)
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);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
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();
}