public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
/**
* 調用默認的構造方法,因爲該類有父類,
* 故而先調用父類的構造方法,在調用本身的構造方法
* 在本身的構造方法中初始一個讀取器和一個掃描器,
* 第①部分!!!
*/
this();
/**
* 向spring 的容器中註冊bean
* 第②部分!!!
*/
register(componentClasses);
/**
* 初始化spring的環境
* 第③部分!!!
*/
refresh();
}
複製代碼
這裏將要解析上述代碼中的register(componentClasses)
這一部分的代碼。。。web
/** * 註冊單個bean給容器 * 好比有新加的類能夠用這個方法 * 可是註冊以後須要手動調用refresh()方法觸發容器解釋註釋 * * 能夠註冊一個配置類 * 也能夠註冊一個bean */ @Override public void register(Class<?>... componentClasses) { Assert.notEmpty(componentClasses, "At least one component class must be specified"); this.reader.register(componentClasses); } 複製代碼
上述代碼中經過 this.reader.register(componentClasses)
完成了配置類的註冊,這裏的 reader
對象就是上一篇文章中提到的 bean的讀取器 AnnotatedBeanDefinitionReader
。spring
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) { registerBean(componentClass); } } 複製代碼
在Spring當中真正的作事情的方法都是經過 do
來開頭完成的。在後續的方法中,會看到不少這類的方法。這裏首先看看 doRegisterBean()
方法實現:api
<T> void doRegisterBean(Class<T> beanClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) { /* * 根據指定的bean建立一個AnnotatedGenericBeanDefinition * 這個AnnotatedGenericBeanDefinition能夠理解爲一個數據結構, * 該結構中包含了類的一些描述信息。好比scope,lazy等等 */ AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } abd.setInstanceSupplier(instanceSupplier); ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); /* * 設置類的做用域 */ abd.setScope(scopeMetadata.getScopeName()); /* * 經過beanNameGenerator生成一個beanName */ String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); /* * 處理類當中的通用註解 * 處理完的數據 存放在 abd 中 */ AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); /* * 當 qualifiers 不爲null 時,處理qualifiers */ if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { /** 若是設置了 @Primary 則將其值設置爲true */ if (Primary.class == qualifier) { abd.setPrimary(true); } else if (Lazy.class == qualifier) { /** 若是設置了 @Lazy 則將其值設置爲true */ abd.setLazyInit(true); } else { /** * 使用了其餘註解,則爲該bean添加一個根據名字自動裝配的限定符 */ abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } for (BeanDefinitionCustomizer customizer : definitionCustomizers) { customizer.customize(abd); } /* * BeanDefinitionHolder 也是一種數據結構 * 將beanName 與 abd 關聯 */ BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); /* * ScopedProxyMode 結合web去理解 */ definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); /* * 將definitionHolder 註冊給 registry * registry 是 AnnotationConfigApplicationContext * AnnotationConfigApplicationContext 在初始化的時候經過調用父類的構造方法實例化一個 DefaultListableBeanFactory * * registerBeanDefinition 就是將 definitionHolder 註冊到 DefaultListableBeanFactory中 */ BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); } 複製代碼
上述改方法的調用過程,最終就是將定義的MyConfig類對應的BeanDefinition放入到beanDefinitionMap中, 至此beanDefinitionMap中對象又增長了一個,變成6個了。 數據結構
/** * 處理類的通用註解 * @param abd spring中bean的描述類 * @param metadata 經過spring中bean的描述類獲取 bean的元數據信息 * * 處理完通用註解後的信息 放回到 spring中bean的描述類(AnnotatedBeanDefinition) */ static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { /** * 處理 @Lazy 註解 */ AnnotationAttributes lazy = attributesFor(metadata, Lazy.class); if (lazy != null) { /** 設置bean的懶加載信息*/ abd.setLazyInit(lazy.getBoolean("value")); } else if (abd.getMetadata() != metadata) { lazy = attributesFor(abd.getMetadata(), Lazy.class); if (lazy != null) { abd.setLazyInit(lazy.getBoolean("value")); } } /** * 處理 @Primary 註解 */ if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true); } /** * 處理 @DependsOn 註解 */ AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); if (dependsOn != null) { abd.setDependsOn(dependsOn.getStringArray("value")); } /** * 處理 @Role 註解 */ AnnotationAttributes role = attributesFor(metadata, Role.class); if (role != null) { abd.setRole(role.getNumber("value").intValue()); } /** * 處理 @Description註解 */ AnnotationAttributes description = attributesFor(metadata, Description.class); if (description != null) { abd.setDescription(description.getString("value")); } } 複製代碼
definitionHolder
註冊給 registry
registry
是 AnnotationConfigApplicationContext
,由於 AnnotationConfigApplicationContext
是 BeanDefinitionRegistry
的實現類。app
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. /** 獲取beanName */ String beanName = definitionHolder.getBeanName(); /** * 註冊 beanDefinition, beanName 與 BeanDefinition 放入Map 中 */ registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. /** 處理別名 */ String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } } 複製代碼
經過上述過程發現,定義的配置類被加載到了容器之中,這樣一來容器中的對象又多了一個。這裏對容器中對象的名稱, 即 BeanDefinitionMap
中的 key
作一個簡要的說明。編輯器
BeanDefinition
的
name
是在Spring 內部寫死的,對應的
BeanDefinition
的實現是
RootBeanDefinition
。
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) { // 經過注接肯定 bean 的名稱 String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); if (StringUtils.hasText(beanName)) { // Explicit bean name found. return beanName; } } // 生成一個默認的惟一的beanName return buildDefaultBeanName(definition, registry); } 複製代碼
determineBeanNameFromAnnotation()
是經過註解生成一個beanName
。好比,在註解中經過屬性value
指定的名稱的類,最終在容器中的beanName
就是這個。ide
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
// 獲取類上的註解 AnnotationMetadata amd = annotatedDef.getMetadata(); // 獲取註解的類型 Set<String> types = amd.getAnnotationTypes(); String beanName = null; for (String type : types) { AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type); if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) { // 獲取value屬性 Object value = attributes.get("value"); // 若是是 字符串 則beanName 就是指定的,不然爲 null if (value instanceof String) { String strVal = (String) value; if (StringUtils.hasLength(strVal)) { if (beanName != null && !strVal.equals(beanName)) { throw new IllegalStateException("Stereotype annotations suggest inconsistent " + "component names: '" + beanName + "' versus '" + strVal + "'"); } beanName = strVal; } } } } return beanName; } 複製代碼
下面是生成一個默認的 beanName
:ui
protected String buildDefaultBeanName(BeanDefinition definition) {
String beanClassName = definition.getBeanClassName(); Assert.state(beanClassName != null, "No bean class name set"); String shortClassName = ClassUtils.getShortName(beanClassName); return Introspector.decapitalize(shortClassName); } 複製代碼
在上述圖中有兩個對象, beanNameGenerator
和 scopeMetadataResolver
分別爲 beanName
生成器和 bean
定義範圍解析器。 在Spring中這兩個對象對應兩個 BeanNameGenerator
和 ScopeMetadataResolver
策略接口。真正的處理邏輯在實現類中完成,這裏對應策略的獲取, 都是經過 new
實現類的方式來完成的。在 AnnotatedBeanDefinitionReader
中對應的代碼以下:this
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver(); 複製代碼
本文使用 mdnice 排版lua