Spring源碼(二)SpringIOC初始化過程源碼分析-基於註解方式

SpringIOC 初始化過程--Bean容器的建立過程(基於AnnotationConfigApplicationContext方式)

Spring 最重要的概念是 IOC 和 AOP,在IOC中最重要的有兩處,一個是建立Bean容器, 一個是初始化Bean,本章就是基於spring5.0.x講述使用AnnotationConfigApplicationContext來說解建立Bean容器;後面文章繼續初始化Bean講解;閱讀Spring源碼是一個枯燥的過程,願君堅持下去;文章最後福利;福不福利的其實不重要,真的但願能堅持下去;java

若是以爲觀看時候來回拉滾動條不方便請使用我的博客觀看git

引言

前面構建了Spring的源碼,在源碼中咱們寫一個啓動Spring容器的例子程序員

IndexDaogithub

public interface IndexDao {

	String testSource();
}
複製代碼

IndexDaoImplweb

@Service
public class IndexDaoImpl implements IndexDao {

	public IndexDaoImpl() {
		System.out.println("constructor");
	}

	public String testSource(){

		return "test \n test2";
	}
}
複製代碼

AppConfigspring

@Configuration
@ComponentScan("cn.haoxy")
public class AppConfig {
}
複製代碼

TestBeanspringboot

public class TestBean {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new     AnnotationConfigApplicationContext();
		applicationContext.register(AppConfig.class);
		applicationContext.refresh();
		IndexDao bean = applicationContext.getBean(IndexDao.class);
		System.out.println(bean.testSource());
		applicationContext.close();
	}
}
複製代碼

build.gradle中引入spring-contextwebsocket

dependencies {
    compile(project(":spring-context"))
    testCompile group: 'junit', name: 'junit', version: '4.12'
}
複製代碼

相似咱們在Maven構建項目時引入的session

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.0.11.RELEASE</version>
</dependency>
複製代碼

在看關於spring源碼的文章時不少都是基於ApplicationContext context = new ClassPathXmlApplicationContext(...)如今都基於springboot項目不多再使用xml的方式去配置,如今不少都是基於註解的方式;因此本文咱們使用AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();來進行講解;數據結構

固然,除了這兩個之外咱們也還有其餘構建 ApplicationContext 的方案可供選擇:

image.png

FileSystemXmlApplicationContext 的構造函數須要一個 xml 配置文件在系統中的路徑,其餘和 ClassPathXmlApplicationContext 基本上同樣。

對於上面的類咱們先混個眼熟就行;後面咱們會再說到的;

啓動過程分析

AnnotationConfigApplicationContext();方法介紹

第一步: 咱們確定要從AnnotationConfigApplicationContext的構造方法開始提及;

AnnotationConfigApplicationContext有父類,故先要執行父類的構造方法;父類的構造方法實例化一個工廠DefaultListableBeanFactory

public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}
複製代碼

到這裏咱們再來看一個類圖:主要是BeanFactory介紹:

image.png
  • ApplicationContext 繼承了 ListableBeanFactory,這個 Listable 的意思就是,經過這個接口,咱們能夠獲取多個 Bean,你們看源碼會發現,最頂層 BeanFactory 接口的方法都是獲取單個 Bean 的。

  • ApplicationContext 繼承了 HierarchicalBeanFactory,Hierarchical 單詞自己已經能說明問題了,也就是說咱們能夠在應用中起多個 BeanFactory,而後能夠將各個 BeanFactory 設置爲父子關係。

  • AutowireCapableBeanFactory 這個名字中的 Autowire 你們都很是熟悉,它就是用來自動裝配 Bean 用的,可是仔細看上圖,ApplicationContext 並無繼承它,不過不用擔憂,不使用繼承,不表明不可使用組合,若是你看到 ApplicationContext 接口定義中的最後一個方法 getAutowireCapableBeanFactory() 就知道了。

  • ConfigurableListableBeanFactory 也是一個特殊的接口,看圖,特殊之處在於它繼承了第二層全部的三個接口,而 ApplicationContext 沒有。這點以後會用到。

  • 而後,請讀者打開編輯器,翻一下 BeanFactory、ListableBeanFactory、HierarchicalBeanFactory、AutowireCapableBeanFactory、ApplicationContext 這幾個接口的代碼,

  • 下面咱們着重介紹一下DefaultListableBeanFactory,咱們能夠看到 ConfigurableListableBeanFactory 只有一個實現類 DefaultListableBeanFactory,並且實現類 DefaultListableBeanFactory 還經過實現右邊的 AbstractAutowireCapableBeanFactory 通吃了右路。因此結論就是,最底下這個傢伙 DefaultListableBeanFactory 基本上是最牛的 BeanFactory 了,這也是爲何這邊會使用這個類來實例化的緣由。上面在的構造方法中實例化了DefaultListableBeanFactory,DefaultListableBeanFactory類中定義了

    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);private volatile List<String> beanDefinitionNames = new ArrayList<>(256);至於這兩個東西是作什麼的,咱們須要先了解一下BeanDefinition;

BeanDefinition介紹

咱們來看下 BeanDefinition 的接口定義:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

   // 咱們能夠看到,默認只提供 sington 和 prototype 兩種,
   // 不少讀者可能知道還有 request, session, globalSession, application, websocket 這幾種,
   // 不過,它們屬於基於 web 的擴展。
   String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
   String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

   // 比較不重要,直接跳過吧
   int ROLE_APPLICATION = 0;
   int ROLE_SUPPORT = 1;
   int ROLE_INFRASTRUCTURE = 2;

   // 設置父 Bean,這裏涉及到 bean 繼承,不是 java 繼承。請參見附錄的詳細介紹
   // 一句話就是:繼承父 Bean 的配置信息而已
   void setParentName(String parentName);

   // 獲取父 Bean
   String getParentName();

   // 設置 Bean 的類名稱,未來是要經過反射來生成實例的
   void setBeanClassName(String beanClassName);

   // 獲取 Bean 的類名稱
   String getBeanClassName();


   // 設置 bean 的 scope
   void setScope(String scope);

   String getScope();

   // 設置是否懶加載
   void setLazyInit(boolean lazyInit);

   boolean isLazyInit();

   // 設置該 Bean 依賴的全部的 Bean,注意,這裏的依賴不是指屬性依賴(如 @Autowire 標記的),
   // 是 depends-on="" 屬性設置的值。
   void setDependsOn(String... dependsOn);

   // 返回該 Bean 的全部依賴
   String[] getDependsOn();

   // 設置該 Bean 是否能夠注入到其餘 Bean 中,只對根據類型注入有效,
   // 若是根據名稱注入,即便這邊設置了 false,也是能夠的
   void setAutowireCandidate(boolean autowireCandidate);

   // 該 Bean 是否能夠注入到其餘 Bean 中
   boolean isAutowireCandidate();

   // 主要的。同一接口的多個實現,若是不指定名字的話,Spring 會優先選擇設置 primary 爲 true 的 bean
   void setPrimary(boolean primary);

   // 是不是 primary 的
   boolean isPrimary();

   // 若是該 Bean 採用工廠方法生成,指定工廠名稱。
   // 一句話就是:有些實例不是用反射生成的,而是用工廠模式生成的
   void setFactoryBeanName(String factoryBeanName);
   // 獲取工廠名稱
   String getFactoryBeanName();
   // 指定工廠類中的 工廠方法名稱
   void setFactoryMethodName(String factoryMethodName);
   // 獲取工廠類中的 工廠方法名稱
   String getFactoryMethodName();

   // 構造器參數
   ConstructorArgumentValues getConstructorArgumentValues();

   // Bean 中的屬性值,後面給 bean 注入屬性值的時候會說到
   MutablePropertyValues getPropertyValues();

   // 是否 singleton
   boolean isSingleton();

   // 是否 prototype
   boolean isPrototype();

   // 若是這個 Bean 是被設置爲 abstract,那麼不能實例化,
   // 經常使用於做爲 父bean 用於繼承,其實也不多用......
   boolean isAbstract();

   int getRole();
   String getDescription();
   String getResourceDescription();
   BeanDefinition getOriginatingBeanDefinition();
}
複製代碼

在Java中,一切皆對象。在JDK中使用java.lang.Class來描述這個對象。

在Spring中,存在bean這樣一個概念,那Spring又是怎麼抽象bean這個概念,用什麼類來描述bean這個對象呢?Spring使用BeanDefinition來描述bean

BeanDefinition有不少子類例如:

image.png

咱們繼續往下看

public AnnotationConfigApplicationContext() {
		/** * 建立一個讀取註解的Bean定義讀取器 */
		this.reader = new AnnotatedBeanDefinitionReader(this);


		//能夠用來掃描包或者類,繼而轉換成BeanDefinition
		//可是實際上咱們掃描包工做不是scanner這個對象來完成的而是
		//spring本身new的一個ClassPathBeanDefinitionScanner
		//這裏的scanner僅僅是爲了程序員可以在外部調用AnnotationConfigApplicationContext對象的scan方法
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
複製代碼

上面代碼首先在AnnotationConfigApplicationContext構造方法中實例化了一個讀取器和掃描器;重點看上面的註釋;

緊接着看下AnnotatedBeanDefinitionReader(this);裏面作了什麼事情

org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)

org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source)

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) {
	
		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				//AnnotationAwareOrderComparator主要能解析@Order註解和@Priority
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
				//ContextAnnotationAutowireCandidateResolver提供處理延遲加載的功能
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}

		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
		//BeanDefinitio的註冊,這裏很重要,須要理解註冊每一個bean的類型
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			//須要注意的是ConfigurationClassPostProcessor的類型是BeanDefinitionRegistryPostProcessor
			//而 BeanDefinitionRegistryPostProcessor 最終實現BeanFactoryPostProcessor這個接口
			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 實現了 MergedBeanDefinitionPostProcessor
			//MergedBeanDefinitionPostProcessor 最終實現了 BeanPostProcessor
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

  //省略
........

		return beanDefs;
	}


複製代碼

上面代碼主要作了如下幾件事:

  • 拿到上面在父類構造方法中實例化的一個工廠DefaultListableBeanFactory

  • DefaultListableBeanFactory工廠中添加AnnotationAwareOrderComparator主要解析@Order註解和@Priority處理優先級;

  • DefaultListableBeanFactory工廠中添加ContextAnnotationAutowireCandidateResolver提供處理延遲加載的功能

  • 註冊spring內部本身定義的bean;並放入到beanDefinitionMapbeanDefinitionNames中,這裏着重看一下

    org.springframework.context.annotation.internalConfigurationAnnotationProcessor=ConfigurationClassPostProcessor這裏有個印象後面會再次說到;

    例如:

image.png

這個方法到這裏就結束了,這就是AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); 所作的事情;

register()方法介紹

咱們接着看下面applicationContext.register(AppConfig.class);

public void register(Class<?>... annotatedClasses) {
		for (Class<?> annotatedClass : annotatedClasses) {
			registerBean(annotatedClass);
		}
	}
public void registerBean(Class<?> annotatedClass) {
		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) {
		/** * 根據指定的bean建立一個BeanDefinition的子類AnnotatedGenericBeanDefinition * 這個AnnotatedGenericBeanDefinition能夠理解爲一個數據結構 * AnnotatedGenericBeanDefinition包含了類的其餘信息,好比一些元信息 * scope,lazy等等 * */

		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
		/** * 判斷這個類是否須要跳過解析 * 經過代碼能夠知道spring判斷是否跳過解析,主要判斷類有沒有加註解 */
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(instanceSupplier);
		/** * 獲得類的做用域 */
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		/** * 把類的做用域添加到數據結構結構中 */
		abd.setScope(scopeMetadata.getScopeName());
		/** * 生成類的名字經過beanNameGenerator */
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		/** * 處理類當中的通用註解 * 分析源碼能夠知道他主要處理 * Lazy DependsOn Primary Role等等註解 * 處理完成以後processCommonDefinitionAnnotations中依然是把他添加到數據結構當中 * */
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

		/** * 若是傳參中帶了這些註解類就會爲true, 不然qualifiers一直爲空 * 由於這裏傳如的是null(doRegisterBean(annotatedClass, null, null, null);) */
		if (qualifiers != null) {
			for (Class<? extends Annotation> qualifier : qualifiers) {
				////若是配置了@Primary註解,若是加了則做爲首選
				if (Primary.class == qualifier) {
					abd.setPrimary(true);
				}
				//懶加載
				else if (Lazy.class == qualifier) {
					abd.setLazyInit(true);
				}
				else {
					//若是使用了除@Primary和@Lazy之外的其餘註解,則爲該Bean添加一個根據名字自動裝配的限定符
					//這裏難以理解,後面會詳細介紹
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
  	//這裏也爲null
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			customizer.customize(abd);
		}

		/** * 這個BeanDefinitionHolder也是一個數據結構 */
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

		/** * ScopedProxyMode 跳過 */
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

		/** * 把上述的這個數據結構註冊給registry * registry就是AnnotationConfigApplicationContext * AnnotationConfigApplicationContext在初始化的時候通過調用父類的構造方法 * 實例化了一個DefaultListableBeanFactory * registerBeanDefinition裏面就是把definitionHolder這個數據結構包含的信息註冊到 * DefaultListableBeanFactory這個工廠 */
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

複製代碼

總結一下這個方法所作的事情:

  • 根據指定的bean建立一個BeanDefinition的子類AnnotatedGenericBeanDefinition

  • 獲得當前類的做用域,當前傳入的是AppConfig.class(默認是singleton);把類的做用域添加到AnnotatedGenericBeanDefinition中

  • 生成bean的名字並放入BeanDefinitionHolder中

  • 處理當前類使用的通用註解,詳細看代碼上的註釋

  • 實例化一個BeanDefinitionHolder,至關於一箇中間媒介;來存放BeanDefinition和beanName而後註冊給registry,這裏的registry就是AnnotationConfigApplicationContext,在AnnotationConfigApplicationContext的父類中實例化了一個DefaultListableBeanFactory;DefaultListableBeanFactory中有個Map集合private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);就是在這個方法中將AppConfig.class放入到beanDefinitionMap 中的;那如今beanDefinitionMap 的size大小就是7個;能夠debbug到BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);方法中看下;最終走了org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition方法中的

    else {
    	// Still in startup registration phase
    	this.beanDefinitionMap.put(beanName, beanDefinition);
    	this.beanDefinitionNames.add(beanName);
    	this.manualSingletonNames.remove(beanName);
    	}
    複製代碼

    applicationContext.register(AppConfig.class);方法到這裏也就結束了;

    下面咱們進入今天的重要部分:

refresh()方法

org.springframework.context.support.AbstractApplicationContext#refresh

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			//準備工做包括設置啓動時間,是否激活標識位,
			// 初始化屬性源(property source)配置
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//返回一個factory 爲何須要返回一個工廠
			//由於要對工廠進行初始化 
            /** 這裏說明一下:若是你使用是的xml配置的方式就會執行 AbstractRefreshableApplicationContext的refreshBeanFactory方法去加載xml配置信息; 由於ClassPathXmlApplicationContext是它的子類;如今咱們使用的是註解配置的方式因此會執行 GenericApplicationContext的refreshBeanFactory方法,這個方法就是隻返回了一個beanFactory**/
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//準備工廠
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.

				//這個方法在當前版本的spring是沒用任何代碼的
				//可能spring期待在後面的版本中去擴展吧
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				//在spring的環境中去執行已經被註冊的 factory processors
				//設置執行自定義的ProcessBeanFactory 和spring內部本身定義的
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				//註冊beanPostProcessor
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 初始化當前 ApplicationContext 的 MessageSource,國際化這裏就不展開說了
				initMessageSource();

				// Initialize event multicaster for this context.
				//初始化應用事件廣播器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 從方法名就能夠知道,典型的模板方法(鉤子方法),
				// 具體的子類能夠在這裏初始化一些特殊的 Bean(在初始化 singleton beans 以前)
				onRefresh();

				// Check for listener beans and register them.
				// 註冊事件監聽器,監聽器須要實現 ApplicationListener 接口。這也不是咱們的重點,過
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 重點,重點,重點
				// 初始化全部的 singleton beans
				//(lazy-init 的除外)
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				// 最後,廣播事件,ApplicationContext 初始化完成
				finishRefresh();
			}
            //.......
複製代碼

prepareRefresh();,obtainFreshBeanFactory();都沒有什麼好說的看上面的註釋就能夠,這裏咱們簡單介紹一下prepareBeanFactory(beanFactory);方法;

prepareBeanFactory()

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
         // 設置 BeanFactory 的類加載器,咱們知道 BeanFactory 須要加載類,也就須要類加載器,
       // 這裏設置爲加載當前 ApplicationContext 類的類加載器
		beanFactory.setBeanClassLoader(getClassLoader());
		//bean表達式解釋器, 爲了可以讓咱們的beanFactory去解析bean表達式
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		//對象與string類型的轉換 <property red="dao">
        //想深刻了解參考 https://blog.csdn.net/pentiumchen/article/details/44026575
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		//添加一個後置管理器ApplicationContextAwareProcessor
		// 可以在bean中得到到各類*Aware(*Aware都有其做用)
        // 這個咱們很經常使用,如咱們會爲了獲取 ApplicationContext 而 implement ApplicationContextAware
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		// 下面幾行的意思就是,若是某個 bean 依賴於如下幾個接口的實現類,在自動裝配的時候忽略它們,
   		// Spring 會經過其餘方式來處理這些依賴。
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

		// 下面幾行就是爲特殊的幾個 bean 賦值,若是有 bean 依賴瞭如下幾個,會注入這邊相應的值,
        //MessageSource 被註冊成爲了一個普通的 bean
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

	// 這個 BeanPostProcessor 也很簡單,在 bean 實例化後,若是是 ApplicationListener 的子類,
    // 那麼將其添加到 listener 列表中,能夠理解成:註冊 事件監聽器
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// 這裏涉及到特殊的 bean,名爲:loadTimeWeaver,這不是咱們的重點,忽略它
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		//意思是若是自定義的Bean中沒有名爲"systemProperties"和"systemEnvironment"的Bean,
		// 則註冊兩個Bena,Key爲"systemProperties"和"systemEnvironment",Value爲Map,
		// 這兩個Bean就是一些系統配置和系統環境信息
		// Register default environment beans.
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}

複製代碼

上面prepareBeanFactory方法只是給beanFactory增長一些特殊的東西例如:表達式解析器,後置處理器,忽略一些特定的類;至此beanFactory中的beanDefinitionMap 的size大小依然仍是7個;

postProcessBeanFactory(beanFactory);是一個空方法;

下面重點介紹一下invokeBeanFactoryPostProcessors(beanFactory);

invokeBeanFactoryPostProcessors()

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		//這裏的getBeanFactoryPostProcessors()是獲取手動給spring的BeanFactoryPostProcessors()
		//何爲手動給spring --> 手動調用AnnotationConfigApplicationContext.addBeanFactoryPostProcessor();
		//因此說自定義的BeanFactoryPostProcessors並不是只有implements BeanFactoryPostProcessors才叫自定義
		//咱們並無手動去調用因此getBeanFactoryPostProcessors()的size = 0
		
		//這裏問: 那若是咱們本身去implements BeanFactoryPostProcessors 那getBeanFactoryPostProcessors()的size還會不會是0?
		//回答: 仍是0! 由於咱們本身implements BeanFactoryPostProcessors必需要加@Component,可是直到如今爲止spring並無開始掃描@Component
		//因此仍是0
		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 (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

複製代碼

進入invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());方法

下面的信息量比較大,咱們先看一下下面代碼中須要的類圖,先熟悉一下,有助於理解;

image.png
public static void invokeBeanFactoryPostProcessors( //List<BeanFactoryPostProcessor> beanFactoryPostProcessors 這個是咱們手動傳過來的 ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();
		//這裏確定是會進的,當前的beanFactory 一直都是 DefaultListableBeanFactory,而DefaultListableBeanFactory是BeanDefinitionRegistry的子類
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			//BeanDefinitionRegistryPostProcessor繼承了BeanFactoryPostProcessor
			//BeanDefinitionRegistryPostProcessor功能比BeanFactoryPostProcessor更強大
			//咱們本身要是想擴展有兩種方式;1:實現BeanFactoryPostProcessor,2,BeanDefinitionRegistryPostProcessor,因此定義了兩個來存放,
			//這裏之因此實例化兩個list的目的是:進行區分,spring對這兩個有不一樣的處理方式

			List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
			//這裏是size=0;上面的代碼註釋中解釋過
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
          /**如咱們本身implements BeanDefinitionRegistryPostProcessor 而且沒有加@Component而是咱們本身手動添加的 ApplicationContext.addBeanFactoryPostProcessor(new TestBeanDefinitionRegistryPostProcessor()); 那麼在下面這句話就會執行重寫的方法;**/
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				} else {
					regularPostProcessors.add(postProcessor);
				}
			}
			//這裏又定義了一個,和上面的區別是,這個currentRegistryProcessors 放的是spring內部本身實現了BeanDefinitionRegistryPostProcessor接口的對象
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
			//BeanDefinitionRegistryPostProcessor 等於 BeanFactoryPostProcessor
			//getBeanNamesForType 根據bean的類型獲取bean的名字 ConfigurationClassPostProcessor
			//這裏的getBeanNamesForType代碼就不展開了大體說下 就是拿到beanDefinitionNames中的7個值去對和BeanDefinitionRegistryPostProcessor對比看是不是他的子類
			//這裏7箇中只有一個ConfigurationClassPostProcessor是它的子類,因此值取到了一個ConfigurationClassPostProcessor
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      //ConfigurationClassPostProcessor咱們在最開始介紹註冊spring內部本身定義的bean時,向beanDefinitionMap添加了6個(AppConfig.calss以外)中,其中一個就是它;
      //這裏解釋一下爲何要在最開始註冊這個呢?由於spring的工廠須要去解析,掃描等等功能 
			//而這些功能都是須要在spring工廠初始化完成以前執行
			//要麼在工廠最開始的時候、要麼在工廠初始化之中,反正不能再以後
			//由於若是在以後就沒有意義,由於那個時候已經須要使用工廠了
     //因此這裏Spring在一開始就註冊了一個BeanFactoryPostProcessor,用來插手SpringFactory的實例化過程
      //而這個類叫作ConfigurationClassPostProcessor
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					//添加到集合currentRegistryProcessors中
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					//添加到processedBeans的Set集合中
					processedBeans.add(ppName);
				}
			}
			//排序不重要,何況currentRegistryProcessors這裏也只有一個數據
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			//合併list,不重要(爲何要合併,由於有咱們自定義個還有spring本身內部實現的)
			registryProcessors.addAll(currentRegistryProcessors);

			/** * //最重要。注意這裏是方法調用 * //調用這個方法 * //循環全部的BeanDefinitionRegistryPostProcessor * //該方法內部postProcessor.postProcessBeanDefinitionRegistry */
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			//這個list只是一個臨時變量,故而要清除
			currentRegistryProcessors.clear();
      // 下面的代碼先不看,等invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);執行完以後咱們回頭再看....
    }

複製代碼

這裏就不總結了,看上面的代碼註釋就很清楚了,下面

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);是重點,咱們進去看看作了什麼事?

private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

		//只有一條數據
		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanDefinitionRegistry(registry);
		}
	}

複製代碼

而後執行了org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry以後執行了org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions咱們着重看下這個方法!

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		//定義一個list 存放 applicationContext 提供的bd
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		//獲取容器中註冊的全部bd名字 這裏會有7個
		String[] candidateNames = registry.getBeanDefinitionNames();

		/** * Full : 加了Configuration註解的類會被Sping標記爲Full * Lite : 其餘註解標記爲Lite */
		//遍歷beanName 拿出的全部bd(BeanDefinition),而後判斷bd時候包含了@Configuration、@Import,@Compent。。。註解
		//這裏循環7,可是有個6個咱們都不須要看,咱們只看AppConfig
		for (String beanName : candidateNames) {
			//根據bean名稱獲得具體的BeanDefinition
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			//檢查是否被處理過
			//若是BeanDefinition中的configurationClass屬性爲full或者lite,則意味着已經處理過了,直接跳過
			//進去下面checkConfigurationClassCandidate方法就會明白這句話的意思
			if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
					ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
			//判斷是不是Configuration類,若是加了Configuration註解下面的這幾個註解就再也不判斷了
			/** * candidateIndicators.add(Component.class.getName()); * candidateIndicators.add(ComponentScan.class.getName()); * candidateIndicators.add(Import.class.getName()); * candidateIndicators.add(ImportResource.class.getName()); */
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				//BeanDefinitionHolder 也能夠當作一個數據結構,將BeanDefinitionHolder添加到上面實例化的一個configCandidates集合中;
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// Return immediately if no @Configuration classes were found
		if (configCandidates.isEmpty()) {
			return;
		}

		// 排序,根據order,不重要
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

		//若是BeanDefinitionRegistry是SingletonBeanRegistry子類的話,
		// 因爲咱們當前傳入的是DefaultListableBeanFactory,是SingletonBeanRegistry 的子類
		// 所以會將registry強轉爲SingletonBeanRegistry
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
				if (generator != null) {
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}

		if (this.environment == null) {
			this.environment = new StandardEnvironment();
		}

		// 實例化ConfigurationClassParser 爲了解析各個配置類
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		//實例化2個set,candidates用於將以前加入的configCandidates進行去重
		//由於可能有多個配置類重複了
		//alreadyParsed用於判斷是否處理過
		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			//掃描包,將去重後的candidates集合傳入;裏面只有一個appConfig
			parser.parse(candidates);
			parser.validate();

			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當中可能包含了特殊類 * 好比ImportBeanDefinitionRegistrar那麼也在這個方法裏面處理 * 可是並非包含在configClasses當中 * configClasses當中主要包含的是importSelector * 由於ImportBeanDefinitionRegistrar在掃描出來的時候已經被添加到一個list當中去了 * */
			//bd 到 map
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);

			candidates.clear();
			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
		if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
		}

		if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
			// Clear cache in externally provided MetadataReaderFactory; this is a no-op
			// for a shared cache since it'll be cleared by the ApplicationContext.
			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
		}
	}

複製代碼

這個方法有點長,並且很重要,須要慢慢看;在這個方法中咱們只須要針對AppConfig這個類看就能夠了其餘6個能夠跳過;

咱們先進入一下checkConfigurationClassCandidate方法,看看是怎麼檢查註解又怎麼標識Full和Lite的;

public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
		String className = beanDef.getBeanClassName();
		if (className == null || beanDef.getFactoryMethodName() != null) {
			return false;
		}

		AnnotationMetadata metadata;
		//......因爲篇幅緣由,省略一些代碼,用一句話來講明一下;這個metadata是怎麼來的
  	  /** 1,若是BeanDefinition 是 AnnotatedBeanDefinition的實例,而且className 和 BeanDefinition中的元數據的類名相同,則直接從BeanDefinition 得到Metadata 2,若是BeanDefinition 是 AbstractBeanDefinition的實例,而且beanDef 有 beanClass 屬性存在 則實例化StandardAnnotationMetadata **/
  
		//判斷當前這個bd中存在的類是否是加了@Configruation註解
		//若是存在則spring認爲他是一個全註解的類
		if (isFullConfigurationCandidate(metadata)) {
			//若是存在Configuration 註解,則爲BeanDefinition 設置configurationClass屬性爲full
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
		}
		//判斷是否加了如下註解,摘錄isLiteConfigurationCandidate的源碼
		// candidateIndicators.add(Component.class.getName());
		// candidateIndicators.add(ComponentScan.class.getName());
		// candidateIndicators.add(Import.class.getName());
		// candidateIndicators.add(ImportResource.class.getName());
		//若是不存在Configuration註解,spring則認爲是一個部分註解類
		else if (isLiteConfigurationCandidate(metadata)) {
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
		}
		else {
			return false;
		}

		// It's a full or lite configuration candidate... Let's determine the order value, if any.
		Integer order = getOrder(metadata);
		if (order != null) {
			beanDef.setAttribute(ORDER_ATTRIBUTE, order);
		}

		return true;
	}


複製代碼

isFullConfigurationCandidate();

public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
		return metadata.isAnnotated(Configuration.class.getName());
	  }

複製代碼

isLiteConfigurationCandidate();

static {
		candidateIndicators.add(Component.class.getName());
		candidateIndicators.add(ComponentScan.class.getName());
		candidateIndicators.add(Import.class.getName());
		candidateIndicators.add(ImportResource.class.getName());
	}

複製代碼

下面咱們重點分析parse方法

public void parse(Set<BeanDefinitionHolder> configCandidates) {
		this.deferredImportSelectors = new LinkedList<>();
		//根據BeanDefinition 的類型 作不一樣的處理,通常都會調用ConfigurationClassParser#parse 進行解析
		//遍歷configCandidates中的BeanDefinitionHolder取出BeanDefinition
		//BeanDefinition中包含了AppConfig的一些屬性信息
		for (BeanDefinitionHolder holder : configCandidates) {
			BeanDefinition bd = holder.getBeanDefinition();
			try {
				//當前bd類型就是AnnotatedBeanDefinition --> true
				if (bd instanceof AnnotatedBeanDefinition) {
					//解析註解對象,而且把解析出來的bd放到map,可是這裏的bd指的是普通的
					//何謂不普通的呢?好比@Bean 和各類beanFactoryPostProcessor獲得的bean不在這裏put
					//可是這裏解析,只是put而已
					//Metadata中主要包含的是解析出來的註解,當前AppConfig 解析出來的註解是@Configuration,@ComponentScan
					//註解什麼時候被解析出來的呢? 就是一開始將AppConfig 加載到BeanDefinitionMap中時;
					parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
				}
				else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
					parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
				}
				else {
					parse(bd.getBeanClassName(), holder.getBeanName());
				}
			}
			catch (BeanDefinitionStoreException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
			}
		}
		//處理延遲加載的importSelect
		processDeferredImportSelectors();
	}
複製代碼

而後進入真正的解析方法org.springframework.context.annotation.ConfigurationClassParser#parse(AnnotationMetadata, String)在這個方法中又調用了org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass方法;

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
			return;
		}
		// 處理Imported 的狀況
		//就是當前這個註解類有沒有被別的類import
		ConfigurationClass existingClass = this.configurationClasses.get(configClass);
		if (existingClass != null) {
			if (configClass.isImported()) {
				if (existingClass.isImported()) {
					existingClass.mergeImportedBy(configClass);
				}
				// Otherwise ignore new imported config class; existing non-imported class overrides it.
				return;
			}
			else {
				// Explicit bean definition found, probably replacing an imports.
				// Let's remove the old one and go with the new one.
				this.configurationClasses.remove(configClass);
				this.knownSuperclasses.values().removeIf(configClass::equals);
			}
		}

		// 遞歸地處理配置類及其超類層次結構。
		SourceClass sourceClass = asSourceClass(configClass);
		do {
      //解析註解並掃描
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);
		//一個map,用來存放掃描出來的bean(注意這裏的bean不是對象,僅僅bean的信息,由於還沒到實例化這一步)
		this.configurationClasses.put(configClass, configClass);
	}
複製代碼

而後進入doProcessConfigurationClass()方法,下面不重要的代碼我就不貼了;

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {

		//處理內部類 通常不會寫內部類
		processMemberClasses(configClass, sourceClass);

		// 處理@PropertySource註釋
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				processPropertySource(propertySource);
			}
			else {
				logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}

		// 處理@ComponentScan註釋
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				//解析掃描的一些基本信息,好比是否過濾,好比是否加入新的包。。。。。includeFilters,excludeFilters等等都是ComponentScan中的屬性
				//掃描普通類-->componentScan ---> com.haoxy
				//這裏掃描出來全部@Component
				//而且把掃描的出來的普通bean放到map當中
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// Check the set of scanned definitions for any further config classes and parse recursively if needed
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					//檢查掃描出來的類當中是否還有@Configuration
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}
		
		//下面是處理@Import imports 3種狀況
		//ImportSelector
		//普通類
		//ImportBeanDefinitionRegistrar
		//這裏和內部地櫃調用時候的狀況不一樣
		/** * 這裏處理的import是須要判斷咱們的類當中時候有@Import註解 * 若是有這把@Import當中的值拿出來,是一個類 * 好比@Import(xxxxx.class),那麼這裏便把xxxxx傳進去進行解析 * 在解析的過程當中若是發覺是一個importSelector那麼就回調selector的方法 * 返回一個字符串(類名),經過這個字符串獲得一個類 * 繼而在遞歸調用本方法來處理這個類 * * 判斷一組類是否是imports(3種import) * *代碼就不貼了,不是我們此次研究的重點 */
		processImports(configClass, sourceClass, getImports(sourceClass), true);
  //..........
}
複製代碼

上面的代碼就是掃描普通類----@Component,包括@Component子類: @Repository @Controller @service;而且放到了BeanDefinitionMap當中;

進入org.springframework.context.annotation.ComponentScanAnnotationParser#parse方法;這裏就是處理ComponentScan註解中的一些屬性;例如scopedProxy,scopeResolver,includeFilters,excludeFilters,lazyInit,basePackages,basePackageClasses,等...咱們直接進入parse方法的org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan方法;這個方法把@ComponentScan中的值傳了過去;

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		//獲取到包名
		for (String basePackage : basePackages) {
			//掃描basePackage路徑下的java文件
			//符合條件的並把它轉成BeanDefinition類型
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				//解析scope屬性
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				//生成bean名稱
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					//若是這個類是AbstractBeanDefinition的子類
					//則爲他設置默認值,好比lazy,init destory
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					//檢查而且處理經常使用的註解
					//這裏的處理主要是指把經常使用註解的值設置到AnnotatedBeanDefinition當中
					//當前前提是這個類必須是AnnotatedBeanDefinition類型的,說白了就是加了註解的類
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					//根據包名掃描到的類加載到beanDefinition map 中
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

複製代碼

掃描候選組件的類路徑方法org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
   if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
      //根據索引得到bean定義,配合spring-context-indexer使用,有興趣得本身去了解一下,這裏不作具體得解析
      return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
   }
   else {
      //掃描得到bean定義
      return scanCandidateComponents(basePackage);
   }
}
複製代碼
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
            Set<BeanDefinition> candidates = new LinkedHashSet<>();
            try {
                //classpath*:cn/haoxy/**/*.class ant path模式串
                String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                        resolveBasePackage(basePackage) + '/' + this.resourcePattern;
                //這裏resources有四個;分別是 TestBean.class,AppConfig.class,IndexDao.class,IndexDaoImpl.class
                Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
                boolean traceEnabled = logger.isTraceEnabled();
                boolean debugEnabled = logger.isDebugEnabled();
                //遍歷resources;
                for (Resource resource : resources) {
                    if (traceEnabled) {
                        logger.trace("Scanning " + resource);
                    }
                    if (resource.isReadable()) {
                        try {
                            MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                       //判斷是不是咱們須要的資源
                      /** * 經過isCandidateComponent(MetadataReader metadataReader)來根據excludeFilters和includeFilters判斷是否能夠進行下一步的操做, * 若是這個資源被排除的filter匹配上,就返回false,表明不是咱們所須要的。 * 若是被包含的filter匹配上,而且他還要經過條件判斷isConditionMatch的話,返回true,表明是咱們須要的資源,能夠進行下一步的操做。 * 這裏咱們插一句Spring有默認的includ類型的filter實現,若是上層傳入的話,就是用上層傳入的,不然就使用默認的, * 默認的是掃描@Component註解以及他的子類@Repository @Controller @service */
                        //顯然這裏只會匹配一個IndexDaoImpl.class
                            if (isCandidateComponent(metadataReader)) {
                                ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                                sbd.setResource(resource);
                                sbd.setSource(resource);
                                if (isCandidateComponent(sbd)) {
                                    if (debugEnabled) {
                                        logger.debug("Identified candidate component class: " + resource);
                                    }
                                    candidates.add(sbd);
                                }
                            //........省
                                    
            }
            catch (IOException ex) {
                throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
            }
            return candidates;
        }
複製代碼

這裏只會有一個IndexDaoImpl符合咱們的要求,放到candidates集合中並返回到doScan方法中;而後解析此類的做用域scope,生成bean名稱等,而後調用registerBeanDefinition(definitionHolder, this.registry);方法把它加入到beanDefinitionMap集合中;

下面咱們看看registerBeanDefinition(definitionHolder, this.registry)方法

org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition方法轉來轉去最後轉到了org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition方法;

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanNam)....
			}
		}
		//全部的 Bean 註冊後會放入這個 beanDefinitionMap 中
		//判斷beanDefinitionMap中是否存在當前bean;之因此判斷是由於咱們能夠配置容許bean覆蓋
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		//顯然這裏是不成立的,咱們並無配置容許bean覆蓋,existingDefinition中也不會存在咱們當前bean
		if (existingDefinition != null) {
			//若是進到這裏說明咱們容許了bean的覆蓋
			if (!isAllowBeanDefinitionOverriding()) {
				// 若是不容許覆蓋的話,拋異常
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName)....
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				//這裏的代碼都是打印日誌 log....
				//日誌內容: 用框架定義的 Bean 覆蓋用戶自定義的 Bean
				//.....
			else if (!beanDefinition.equals(existingDefinition)) {
				//log....
				//日誌內容: 用新的 Bean 覆蓋舊的 Bean
			}
			else {
				//log....
				//日誌內容: 用同等的 Bean 覆蓋舊的 Bean,這裏指的是 equals 方法返回 true 的 Bean
			}
			//覆蓋bean
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			//上面的if不成立就來到了這裏;若是是普通bean(IndexDaoImpl等),這裏返回是true,
			// 若是是AppConfig等特殊bean,Spring一開始就加載的會走下面的else
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					//以beanName爲key,beanDefinition爲value put 到 beanDefinitionMap中;
                    //注意,"註冊Bean" 這個動做結束,Bean 依然尚未初始化,咱們後面會有大篇幅說初始化過程,
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					//將beanName 添加到 beanDefinitionNames集合中
					this.beanDefinitionNames = updatedDefinitions;
					if (this.manualSingletonNames.contains(beanName)) {
						Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			}
			//特殊bean
			else {
				// Still in startup registration phase
               //一樣是以beanName爲key,beanDefinition爲value put 到 beanDefinitionMap中;
				this.beanDefinitionMap.put(beanName, beanDefinition);
                //將beanName 添加到 beanDefinitionNames集合中
				this.beanDefinitionNames.add(beanName);
                //這LinkedHashSet存放的是:environment,systemProperties,systemEnvironment
                //都是一些系統環境,系統屬性,這裏對咱們不重要
				this.manualSingletonNames.remove(beanName);
			}
            // 這個不重要,在預初始化的時候會用到,沒必要管它。
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}
複製代碼

這時候beanDefinitionMap的size大小就是8個了;而後放到beanDefinitions集合中返回;這裏只是把它加入到beanDefinitionMap集合中尚未進行初始化;上面就是@ComponentScan註解做用的掃描BeanDefination的所有過程了。這一篇文章終於結束了,好累,本身總結了一遍印象更深入一些;下一篇文章開始bean的建立過程以及初始化;

福利:

帶中文註釋的Spring源碼, 博客總結

使用博客觀看效果更佳

相關文章
相關標籤/搜索