Spring5源碼分析-註冊配置類

 上一篇:Spring5源碼分析-容器自身初始化已經準備好容器,這一篇就是要本身的Java配置類註冊到beanDefinitionMaps當中,好讓ConfigurationCLassPostProcessor對Java配置類上面的註解進行分析,是否執行包路徑下符合Spring規則的類進行掃描並完成註冊和實例化等java

方法的調用棧:spring

doRegisterBean:254, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
registerBean:147, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
register:137, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
register:183, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:12, AutowiredAnnotationMain (com.jv.spring.autowiredannotation)

核心方法代碼註釋:數組

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {
		//根據配置類生成的BeanDefinition
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		//根據@Conditional是否要註冊這個BeanDefinition  在SpringBoot中大量使用
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(supplier);
		//獲取類的Scope(ConfigurableBeanFactory中定義了範圍--singlton/prototype )
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		//生成Bean的名稱  若是註解中沒有指定Bean的名稱,則默認按照這種方式生成:類名-FooServiceImpl BeanName-fooServiceImpl
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		//掃描並處理Bean的一些特性,好比Lazy Primary DependsON等等 ,如abd.setLazyInit(true)
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		//目前只看了Spring的源碼,默認傳過來的qualifiers都是爲NULL的,能夠本身改一下Spring的代碼,調用時傳一個Annotation數組過來,數組裏麪包含@Primary@Lazy
		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));
				}
			}
		}
		if (customizers != null) {
			for (BeanDefinitionCustomizer customizer : customizers) {
				customizer.customize(abd);
			}
		}
		//一個BeanDefinition包裝類,把AnnotatedGenericBeanDefinition和名稱放到袋子中
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

		/**
		 * 裏面根據definitionHolder.getBeanDefinition複製了一個BeanDefinition,也就是proxyBeanDefinition
		 * 原來的BeanDefinition重置了兩個參數:
		 * ——autowireCandidate=0 不能被用於自動注入
		 * ——primary=false 再也不是主Bean
		 *
		 * 說了這麼多,我也不知道何時會用到,聽說是SpringMVC很是有用,只是用Spring的話,還用不到,後面再關注具體的使用場景和細節
		 */
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		//將自定義的配置類(XXXConfig.class)掃描、解析並放到beanDefinitionMap中
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

總結:就是將我本身定義的AutowiredAnnotationConfig對應的BeanDefinition放到beanDefinitionMaps當中,其餘的分支流程其實都進不去,好比qualifiers customizers都是null,因此涉及到的分支也不會被執行。app

截止到目前Spring尚未提供什麼擴展點給開發人員使用,接下來就會慢慢開始接觸到很是多的擴展點和咱們經常使用一些註解的邏輯實現。這裏還有一個番外篇:使用register()直接註冊一個非@Configuration修飾的Bean,能夠直接getBean()源碼分析

相關文章
相關標籤/搜索