首先回顧下整個流程:
先新建一個BeanFactoryPostProcessor,然後在配置文件中注入這個類
public class MyPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("==> come to myPostProcessor ...");
}
}
<bean id="myPostProcessor" class="org.springframework.MyPostProcessor"/>
下面跟進一下代碼:
refresh() ——> invokeBeanFactoryPostProcessors(beanFactory) ——> PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
// 1.判斷beanFactory是否爲BeanDefinitionRegistry,beanFactory爲DefaultListableBeanFactory,
// 而DefaultListableBeanFactory實現了BeanDefinitionRegistry接口,因此這邊爲true
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 用於存放普通的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 用於存放BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 2.首先處理入參中的beanFactoryPostProcessors
// 遍歷所有的beanFactoryPostProcessors, 將BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor區分開
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// 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.
// 用於保存本次要執行的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 3.調用所有實現PriorityOrdered接口的BeanDefinitionRegistryPostProcessor實現類
// 找出所有實現BeanDefinitionRegistryPostProcessor接口的Bean的beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//校驗是否實現了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//獲取ppName對應的bean實例, 添加到currentRegistryProcessors中,
// beanFactory.getBean: 這邊getBean方法會觸發創建ppName對應的bean對象, 目前暫不深入解析
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 將要被執行的加入processedBeans,避免後續重複執行
processedBeans.add(ppName);
}
}
//進行排序(根據是否實現PriorityOrdered、Ordered接口和order值來排序)
sortPostProcessors(currentRegistryProcessors, beanFactory);
//添加到registryProcessors(用於最後執行postProcessBeanFactory方法)
registryProcessors.addAll(currentRegistryProcessors);
//遍歷currentRegistryProcessors, 執行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//執行完畢後, 清空currentRegistryProcessors
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 4.調用所有實現了Ordered接口的BeanDefinitionRegistryPostProcessor實現類(過程跟上面的步驟3基本一樣)
// 找出所有實現BeanDefinitionRegistryPostProcessor接口的類, 這邊重複查找是因爲執行完上面的BeanDefinitionRegistryPostProcessor,
// 可能會新增了其他的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);
registryProcessors.addAll(currentRegistryProcessors);
// 遍歷currentRegistryProcessors, 執行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 5.最後, 調用所有剩下的BeanDefinitionRegistryPostProcessors
boolean reiterate = true;
while (reiterate) {
reiterate = false;
//找出所有實現BeanDefinitionRegistryPostProcessor接口的類
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);
// 如果有BeanDefinitionRegistryPostProcessor被執行, 則有可能會產生新的BeanDefinitionRegistryPostProcessor,
// 因此這邊將reiterate賦值爲true, 代表需要再循環查找一次
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 遍歷currentRegistryProcessors, 執行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 6.調用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法(BeanDefinitionRegistryPostProcessor繼承自BeanFactoryPostProcessor)
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 7.最後, 調用入參beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 到這裏 , 入參beanFactoryPostProcessors和容器中的所有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!
// 8.找出所有實現BeanFactoryPostProcessor接口的類
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 用於存放實現了PriorityOrdered接口的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// 用於存放實現了Ordered接口的BeanFactoryPostProcessor的beanName
List<String> orderedPostProcessorNames = new ArrayList<>();
// 用於存放普通BeanFactoryPostProcessor的beanName
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// 遍歷postProcessorNames, 將BeanFactoryPostProcessor按實現PriorityOrdered、實現Ordered接口、普通三種區分開
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);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// 9.調用所有實現PriorityOrdered接口的BeanFactoryPostProcessor
// 對priorityOrderedPostProcessors排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 遍歷priorityOrderedPostProcessors, 執行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// 10.調用所有實現Ordered接口的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
// 獲取postProcessorName對應的bean實例, 添加到orderedPostProcessors, 準備執行
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
//遍歷orderedPostProcessors, 執行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
// 11.調用所有剩下的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
//遍歷nonOrderedPostProcessors, 執行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
// 12.清除元數據緩存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType),
// 因爲後處理器可能已經修改了原始元數據,例如, 替換值中的佔位符...
beanFactory.clearMetadataCache();
}
1、整個 invokeBeanFactoryPostProcessors 方法圍繞兩個接口,BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor,其中 BeanDefinitionRegistryPostProcessor 繼承了 BeanFactoryPostProcessor 。BeanDefinitionRegistryPostProcessor 主要用來在常規 BeanFactoryPostProcessor 檢測開始之前註冊其他 Bean 定義,說的簡單點,就是 BeanDefinitionRegistryPostProcessor 具有更高的優先級,執行順序在 BeanFactoryPostProcessor 之前。
2、整個 invokeBeanFactoryPostProcessors 方法操作了 3 種 bean 對象:
- 入參 beanFactoryPostProcessors:取的是 AbstractApplicationContext 類的 beanFactoryPostProcessors 屬性值,也就是在之前已經添加到 beanFactoryPostProcessors 中的 BeanFactoryPostProcessor。
- BeanDefinitionRegistryPostProcessor 接口實現類:實現了 BeanDefinitionRegistryPostProcessor 接口,並且註冊到 Spring IoC容器中。
- 常規 BeanFactoryPostProcessor 接口實現類:實現了 BeanFactoryPostProcessor 接口,並且註冊到 Spring IoC容器中。
如果將自定義 BeanFactoryPostProcessor 放到AbstractApplicationContext 類的 beanFactoryPostProcessors 屬性中,在‘’入參 beanFactoryPostProcessors“時就能加載到?如果要加入到入參beanFactoryPostProcessors(當項目啓動時確保在refresh之前加載到這個 BeanFactoryPostProcessor),可以新建一個 ApplicationContextInitializer 的實現類 SpringApplicationContextInitializer ,並在 initialize 方法中寫我們的邏輯 。
package com.joonwhee.open.demo.spring;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
public class SpringApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
FirstBeanDefinitionRegistryPostProcessor firstBeanDefinitionRegistryPostProcessor = new FirstBeanDefinitionRegistryPostProcessor();
// 將自定義的firstBeanDefinitionRegistryPostProcessor添加到應用上下文中
applicationContext.addBeanFactoryPostProcessor(firstBeanDefinitionRegistryPostProcessor);
// ...自定義操作
System.out.println("SpringApplicationContextInitializer#initialize");
}
}
<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>
com.joonwhee.open.demo.spring.SpringApplicationContextInitializer
</param-value>
</context-param>
擴展: 那麼爲什麼要這麼做呢? 因爲 customizeContext 方法,是 Spring 提供給開發者的一個擴展點,用於自定義應用上下文,並且在 refresh() 方法前就被調用。 下面說一下項目啓動時 customizeConxt 的加載位置。
web.xml 是一個使用了 Spring 框架的項目的最基本的配置,配置了 ContextLoaderListener 和 contextConfigLocation。其中 ContextLoaderListener 是 Spring 的入口,而 contextConfigLocation 是 Spring 配置文件的路徑。下面將從 ContextLoaderListener#contextInitialized 開始 IoC 的構建。
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>open-joonwhee-service WAR</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:config/spring/appcontext-*.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
進入 ContextLoaderListener#contextInitialized 方法之前,由於 ContextLoaderListener 繼承了 ContextLoader,需要先將 ContextLoader 的成員變量初始化。在 ContextLoader 的成員變量中,defaultStrategies 屬性的初始化比較重要,下面拿出來單獨介紹。
private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties"; private static final Properties defaultStrategies; static { // Load default strategy implementations from properties file. // This is currently strictly internal and not meant to be customized // by application developers. try { // 1.根據 DEFAULT_STRATEGIES_PATH(ContextLoader.properties) 和 ContextLoader.class 構建 ClassPathResource, // path在這邊爲相對路徑,全路徑爲:org.springframework.web.context.ContextLoader.properties ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class); // 2.加載resource的屬性,在這邊我們拿到了默認的WebApplicationContext,即:XmlWebApplicationContext defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); } catch (IOException ex) { throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage()); } }
接着,正式進入 ContextLoaderListener#contextInitialized 方法
@Override public void contextInitialized(ServletContextEvent event) { initWebApplicationContext(event.getServletContext()); } public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { // 1.校驗WebApplicationContext 是否已經初始化過,如果已經初始化,則拋出異常 if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { throw new IllegalStateException( "Cannot initialize context because there is already a root application context present - " + "check whether you have multiple ContextLoader* definitions in your web.xml!"); } Log logger = LogFactory.getLog(ContextLoader.class); servletContext.log("Initializing Spring root WebApplicationContext"); if (logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } long startTime = System.currentTimeMillis(); try { // Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown. if (this.context == null) { // 2.創建一個WebApplicationContext並保存到context屬性 this.context = createWebApplicationContext(servletContext); } if (this.context instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> // determine parent for root web application context, if any. ApplicationContext parent = loadParentContext(servletContext); cwac.setParent(parent); } // 3.配置和刷新web應用上下文 configureAndRefreshWebApplicationContext(cwac, servletContext); } } // 4.設置WebApplicationContext屬性 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); ClassLoader ccl = Thread.currentThread().getContextClassLoader(); if (ccl == ContextLoader.class.getClassLoader()) { currentContext = this.context; } else if (ccl != null) { currentContextPerThread.put(ccl, this.context); } if (logger.isDebugEnabled()) { logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); } if (logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); } return this.context; } catch (RuntimeException ex) { logger.error("Context initialization failed", ex); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex); throw ex; } catch (Error err) { logger.error("Context initialization failed", err); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err); throw err; } }
其中第三步 configureAndRefreshWebApplicationContext 配置刷新應用上下文
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) { // 1.如果應用上下文id是原始默認值,則根據相關信息生成一個更有用的 if (ObjectUtils.identityToString(wac).equals(wac.getId())) { // The application context id is still set to its original default value // -> assign a more useful id based on available information // 1.1 從servletContext中解析初始化參數contextId(可以在web.xml中配置) String idParam = sc.getInitParameter(CONTEXT_ID_PARAM); if (idParam != null) { // 1.1.1 如果idParam不爲空, 則設置爲wac的Id屬性 wac.setId(idParam); } else { // Generate default id... // 1.1.2 如果idParam爲空, 則生成默認的id, 例如: org.springframework.web.context.WebApplicationContext: wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath())); } } // 2.爲應用上下文設置servletContext wac.setServletContext(sc); // 3.從servletContext中解析初始化參數contextConfigLocation(可以在web.xml中配置, 這個參數一般我們都會設置) String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM); if (configLocationParam != null) { // 4.設置wac的configLocations屬性值爲configLocationParam wac.setConfigLocation(configLocationParam); } // The wac environment's #initPropertySources will be called in any case when the context // is refreshed; do it eagerly here to ensure servlet property sources are in place for // use in any post-processing or initialization that occurs below prior to #refresh ConfigurableEnvironment env = wac.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { // 5.初始化屬性源(主要是將servletContextInitParams的佔位類替換成sc) ((ConfigurableWebEnvironment) env).initPropertySources(sc, null); } // 6.自定義上下文 customizeContext(sc, wac); // 7.應用上下文的刷新 wac.refresh(); }
第六步 customizeContext 自定義上下文
protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) { // 1.確定應用上下文的初始化類 List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses = determineContextInitializerClasses(sc); // 2.如果initializerClasses不爲空, 遍歷處理initializerClasses for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses) { Class<?> initializerContextClass = GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class); if (initializerContextClass != null && !initializerContextClass.isInstance(wac)) { throw new ApplicationContextException(String.format( "Could not apply context initializer [%s] since its generic parameter [%s] " + "is not assignable from the type of application context used by this " + "context loader: [%s]", initializerClass.getName(), initializerContextClass.getName(), wac.getClass().getName())); } // 3.實例化initializerClass, 並添加到contextInitializers中 this.contextInitializers.add(BeanUtils.instantiateClass(initializerClass)); } AnnotationAwareOrderComparator.sort(this.contextInitializers); // 4.遍歷實例化後的contextInitializers for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) { // 5.調用initializer的initialize方法,進行自定義初始化wac操作 initializer.initialize(wac); } }
3、整個 invokeBeanFactoryPostProcessors 方法多次調用getBeanNamesForType,如何找出所有實現類的beanName?下面挖一下(之前妄想猜測有能通過接口反射找到所有實現類的方法,實際上只是將配置文件中的bean加載到beanFactory,然後再進行遍歷驗證來處理)
// 找出所有實現BeanDefinitionRegistryPostProcessor接口的Bean的beanName
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
//方法簽名
//第一個參數type表示要查找的bean的類型
//includeNonSingletons 是否考慮非單例bean
//allowEagerInit 是否允許提早初始化
String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
//具體的實現代碼,我們從DefaultListableBeanFactory中分析
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
//配置還未被凍結或者類型爲null或者不允許早期初始化
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
//值得注意的是,不管type是否不爲空,allowEagerInit是否爲true
//只要isConfigurationFrozen()爲false就一定不會走這裏
//因爲isConfigurationFrozen()爲false的時候表示BeanDefinition
//可能還會發生更改和添加,所以不能進行緩存
//如果允許非單例的bean,那麼從保存所有bean的集合中獲取,否則從
//單例bean中獲取
Map<Class<?>, String[]> cache =
(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
String[] resolvedBeanNames = cache.get(type);
if (resolvedBeanNames != null) {
return resolvedBeanNames;
}
//如果緩存中沒有獲取到,那麼只能重新獲取,獲取到之後就存入緩存
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
//DefaultListableBeanFactory
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<String>();
// Check all bean definitions.
for (String beanName : this.beanDefinitionNames) {
// Only consider bean as eligible if the bean name
// is not defined as alias for some other bean.
//如果是別名,跳過(這個集合會保存所有的主beanName,並且不會
//保存別名,別名由BeanFactory中別名map維護,這裏個人認爲是一種防禦性編程)
if (!isAlias(beanName)) {
try {
//獲取合併的BeanDefinition,合併的BeanDefinition是指
//spring整合了父BeanDefinition的屬性,將其他類型的
//BeanDefinition變成了RootBeanDefintion
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Only check bean definition if it is complete.
//抽象的BeanDefinition是不做考慮,抽象的就是拿來繼承的
//如果允許早期初始化,那麼直接短路,進入方法體
//如果不允許早期初始化,那麼需要進一步判斷,如果是不允許早期初始化的,
//並且beanClass已經被加載或者它是可以早期初始化的,那麼如果當前bean是工廠bean,並且指定的bean又是工廠
//那麼這個bean就必須被早期初始化,也就是說就不符合我們制定的allowEagerInit爲false的情況,直接跳過
if (!mbd.isAbstract() && (allowEagerInit ||
((mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading())) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
// In case of FactoryBean, match object created by FactoryBean.
//如果當前bean是工廠bean
boolean isFactoryBean = isFactoryBean(beanName, mbd);
//如果允許早期初始化,那麼基本上會調用最後的isTypeMatch方法
//這個方法會導致工廠的實例化,但是當前不允許進行早期實例化
//在不允許早期實例化的情況下,如果當前bean是工廠bean,那麼它只能在已經被創建的情況下調用isTypeMatch進行匹配判斷
//否則只能宣告匹配失敗,返回false
boolean matchFound = (allowEagerInit || !isFactoryBean || containsSingleton(beanName)) &&
(includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type);
//如果沒有匹配到並且它是個工廠bean,那麼加上&前綴,表示我要獲取FactoryBean類型的bean
if (!matchFound && isFactoryBean) {
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
}
//找到便記錄到result集合中,等待返回
if (matchFound) {
result.add(beanName);
}
}
}
catch (CannotLoadBeanClassException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably contains a placeholder: let's ignore it for type matching purposes.
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
}
onSuppressedException(ex);
}
catch (BeanDefinitionStoreException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably contains a placeholder: let's ignore it for type matching purposes.
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
}
onSuppressedException(ex);
}
}
}
// Check manually registered singletons too.
//從單例註冊集合中獲取,這個單例集合是保存spring內部注入的單例對象
//它們有特點就是沒有BeanDefinition
for (String beanName : this.manualSingletonNames) {
try {
// In case of FactoryBean, match object created by FactoryBean.
//如果是工廠bean,那麼調用其getObjectType去匹配是否符合指定類型
if (isFactoryBean(beanName)) {
if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
result.add(beanName);
// Match found for this bean: do not match FactoryBean itself anymore.
continue;
}
// In case of FactoryBean, try to match FactoryBean itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
}
//如果沒有匹配成功,那麼匹配工廠類
// Match raw bean instance (might be raw FactoryBean).
if (isTypeMatch(beanName, type)) {
result.add(beanName);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Shouldn't happen - probably a result of circular reference resolution...
if (logger.isDebugEnabled()) {
logger.debug("Failed to check manually registered singleton with name '" + beanName + "'", ex);
}
}
}
return StringUtils.toStringArray(result);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);在查找指定類型的bean的時候,spring會對BeanDefinition進行合併,以保證某個bean信息是完整的 。
boolean isFactoryBean = isFactoryBean(beanName, mbd); 其中isFactoryBean層級較深,這裏只描述一下方法內容:首先判斷對應BeanDefinition是否存在工廠方法,如果不存在,很好說,直接判斷beanClass即可,如果存在工廠方法,那麼又得判斷是否存在factorybeanname屬性,如果不存在,那麼這是一個靜態工廠,判斷其方法的返回類型是否爲FactoryBean類型即可,如果存在,那麼事情就稍微複雜了,如果對應的factorybeanname是一個普通的類,那麼也只需要判斷其返回返回值類型即可,但是如果這個factorybeanname是一個實現了FactoryBean接口的類,那麼我們需要實例化,然後調用FactoryBean的getObjectType方法獲取到對應的對象類型,在判斷它的工廠方法的返回類型。