環(huán)境版本:java8,spring5.2.x,maven3.6
@Configuration注冊類的全過程醉鳖,話不多說驮樊,上代碼罕偎,我這里是從關(guān)鍵的方法人手了
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
//1, 為我們傳入的class創(chuàng)建bean的定義
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
// 2. 判斷當(dāng)前類是否應(yīng)當(dāng)跳過(根據(jù) @Conditional 判斷)
if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
abd.setInstanceSupplier(supplier);
// 3. 從類元數(shù)據(jù)中解析獲取 scope 作用范圍信息(默認(rèn)為 singleton)
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
//4缠犀,為改bean定義設(shè)置作用范圍
abd.setScope(scopeMetadata.getScopeName());
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
//5. 處理通用注解(例如 @Lazy 等)
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
int var10;
int var11;
if (qualifiers != null) {
Class[] var9 = qualifiers;
var10 = qualifiers.length;
for(var11 = 0; var11 < var10; ++var11) {
Class<? extends Annotation> qualifier = var9[var11];
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
BeanDefinitionCustomizer[] var13 = customizers;
var10 = customizers.length;
for(var11 = 0; var11 < var10; ++var11) {
BeanDefinitionCustomizer customizer = var13[var11];
customizer.customize(abd);
}
}
//6. 創(chuàng)建 BeanDefinition 的 BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 7. 應(yīng)用 ScopedProxyMode
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 8. 注冊 BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
說明:
doRegisterBean方法很復(fù)雜乳讥,我們的主題是@Configuration,所以省略一些不重要的代碼知残。
- 為我們傳入的 class 創(chuàng)建對應(yīng)的 BeanDefinition 并進(jìn)行相關(guān)默認(rèn)值的初始化靠瞎,這里的 BeanDefinition 指的是 AnnotatedGenericBeanDefinition,它是 GenericBeanDefinition 的子類,主要添加了對注解元數(shù)據(jù)的支持(這點通過下面的構(gòu)造器代碼也能夠看出來乏盐,它將類元數(shù)據(jù) metadata 單獨進(jìn)行保存佳窑,這個 StandardAnnotationMetadata 中有一個屬性 annotations 就是用來專門保存類的注解信息的)。
public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
this.setBeanClass(beanClass);
this.metadata = AnnotationMetadata.introspect(beanClass);
}
- 根據(jù) @Conditional 注解來判斷當(dāng)前 Bean 實例化是否需要跳過(即當(dāng)前不滿足 @Conditional 注解條件)父能。
public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
return this.shouldSkip(metadata, (ConfigurationPhase)null);
}
將獲取到的 scope 賦值給 BeanDefinition(這步完成后剛剛創(chuàng)建的 AnnotatedGenericBeanDefinition 對象的 scope 屬性為 scope 值)神凑。
獲取并處理類的通用注解(@Lazy、@Primary法竞、@DependsOn耙厚、@Role 和 @Description)信息,這里調(diào)用的是 processCommonDefinitionAnnotations 方法岔霸,這個方法沒有什么太大營養(yǎng)薛躬,就是把你的類元數(shù)據(jù)中的注解信息取出來,然后依次檢查是否設(shè)置了對應(yīng)的注解呆细,并將值賦給剛剛創(chuàng)建的 BeanDefinition 對象
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
} else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), (Class)Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
}
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
abd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
abd.setDescription(description.getString("value"));
}
}
創(chuàng)建 BeanDefinition 對應(yīng)的 BeanDefinitionHolder 對象型宝,這個對象沒什么太多特殊的作用,就是持有一個 BeanDefinition 對象絮爷。
接下里調(diào)用 applyScopedProxyMode 方法來應(yīng)用(創(chuàng)建)一個 ScopedProxyMode 對象(跟 @Configuration 無關(guān)趴酣,所以不去過細(xì)分析)。
最后一步坑夯,也就是最重要的注冊 BeanDefinition 到 BeanDefinitionMap 中岖寞,這里直接進(jìn)方法看代碼。
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
//9柜蜈,注冊bean的定義
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
}
}
- 這里首先使用 Bean 的主名稱進(jìn)行注冊仗谆,這個主名稱其實就是我們的 Bean 名稱(當(dāng)前的名稱就是我們剛剛傳入的配置類的類名 SpringConfig),然后又使用了標(biāo)簽進(jìn)行注冊淑履,這里我們先不考慮標(biāo)簽隶垮,所以直接使用 Bean 名稱進(jìn)行注冊,繼續(xù)跟進(jìn) registry.registerBeanDefinition 方法秘噪。
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
//10狸吞,驗證名稱和定義不能為空
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// 11. 如果當(dāng)前的 BeanDefinition 是 AbstractBeanDefinition 子類則驗證對象信息
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var8) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
}
}
BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
//兩個分支-> 如果容器中已經(jīng)存在了該 BeanName 所對應(yīng)的 BeanDefinition
if (existingDefinition != null) {
// 如果不允許重寫(替換)原始的 BeanDefinition直接拋異常
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
// 如果允許替換則比較兩個 BeanDefinition 的 @Role 值
if (existingDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(existingDefinition)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
// 將新的 BeanDefinition 對象添加到 Map 中
this.beanDefinitionMap.put(beanName, beanDefinition);
}
// 12. 如果 Map 中不存在 BeanName 所對應(yīng)的的 BeanDefinition
else {
//13. 判斷當(dāng)前工廠是否已經(jīng)開始創(chuàng)建 Bean 對象
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
// 將該 BeanDefinition 添加到 Map 中
this.beanDefinitionMap.put(beanName, beanDefinition);
//// 按照原始 BeanName List 大小 +1 創(chuàng)建新 BeanName List
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
// 將原始 BeanName List 內(nèi)容復(fù)制到新 BeanName List 中 updatedDefinitions.addAll(this.beanDefinitionNames);
// 將新添加的 BeanName 添加到新的 BeanName List 中
updatedDefinitions.add(beanName);
// 讓原始的 BeanName List 指向新 BeanName List
this.beanDefinitionNames = updatedDefinitions;
// 移除工廠內(nèi)部的手動單例名稱集
this.removeManualSingletonName(beanName);
}
} else {
// 14. 沒有正在創(chuàng)建bean,將 BeanDefinition 直接添加到 Map 中
this.beanDefinitionMap.put(beanName, beanDefinition);
// 15. 如果非正在創(chuàng)建則直接將 BeanName 添加到 BeanName List 中
this.beanDefinitionNames.add(beanName);
// 從 manualSingletonNames 移除 BeanName
this.removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 如果 Map 中已存在 BeanName 對應(yīng)的 BeanDefinition 或者 BeanName 為單例模式
if (existingDefinition == null && !this.containsSingleton(beanName)) {
if (this.isConfigurationFrozen()) {
this.clearByTypeCache();
}
} else {
// 重置 BeanName 在容器中對應(yīng)的 BeanDefinition
this.resetBeanDefinition(beanName);
}
}
驗證 BeanName 和 BeanDefinition 不為空。
然后判斷當(dāng)前的 BeanDefinition 是否是 AbstractBeanDefinition 的子類指煎,如果是的話就調(diào)用 prepareMethodOverrides 方法就對其抽象方法進(jìn)行驗證蹋偏,判斷這個 BeanDefinition 是否正確重寫了它的抽象方法。
接著判斷當(dāng)前容器中是否已經(jīng)存在 BeanName 所對應(yīng)的 BeanDefinition(BeanDefinition 存儲于 BeanDefinitionMap 中贯要,鍵為 BeanName暖侨,值為 BeanDefinition),如果已經(jīng)存在就判斷是否可以進(jìn)行替換等一系列邏輯崇渗,如果不存在就進(jìn)入 else 語句塊。
接著調(diào)用 hasBeanCreationStarted 判斷當(dāng)前工廠是否已經(jīng)開始創(chuàng)建 Bean(這個方法里面主要是通過判斷 alreadyCreated 容器內(nèi)是否為空,因為當(dāng)工廠將要實例化創(chuàng)建一個 Bean 對象的時候都會先將其存放在這個 alreadyCreated 容器中)宅广,如果此時工廠還未開始創(chuàng)建 Bean 對象葫掉,那么我們就可以直接將當(dāng)前的 BeanName 和 BeanDefinition 直接添加到容器中。但是如果此時工廠已經(jīng)開始創(chuàng)建 Bean 對象了(根據(jù) BeanDefinition)跟狱,那么正如它注釋中所講這個時候再對 BeanDefinitionMap 和 BeanDefinitionNames 來進(jìn)行操作就是不安全的了俭厚,因此這個時候我們就需要通過加鎖來保證整個的添加操作線程安全。但是在什么情況下會出現(xiàn)這個問題呢驶臊,顯然如果我們按照正常的代碼邏輯到目前為止還沒有進(jìn)行任何的 Bean 的創(chuàng)建工作挪挤,但是假如在我們自己的業(yè)務(wù)代碼中,在另一個線程中关翎,當(dāng)容器開始創(chuàng)建 Bean 對象時扛门,我們直接獲取到容器中的這個 DefaultListableBeanFactory,并調(diào)用這個 registerBeanDefinition 方法對其當(dāng)中的 BeanDefinitionMap 進(jìn)行添加或刪除等修改操作纵寝,那么就會造成非線程安全的問題(這里的安全問題主要是指雖然 BeanDefinitionMap 是 concurrentHashMap 的線程安全 Map论寨,對于將 BeanDefinition 添加到其中的操作時線程安全的,但是我們無法保證 BeanDefinitionName 和 BeanDefinition 能夠同時被分別添加到兩個容器中(非原子操作)爽茴,即整個操作流程是非線程安全的)葬凳。并且還可以注意到在下面的 BeanDefinitionNames 這個 List 當(dāng)中順序保存了所有的 BeanName,在鎖的過程中我們鎖的是 BeanDefinitionMap 這個對象室奏,并沒有鎖住這個 BeanDefinitionNames火焰,因此跟上面一樣的道理,假如有其他的線程正在容器中遍歷讀取 BeanDefinitionNames List 當(dāng)中的信息對 List 當(dāng)中的 Bean 進(jìn)行實例化胧沫,那么此時我們在當(dāng)前線程對 BeanDefinitionNames List 直接進(jìn)行添加操作會引發(fā)快速失敳颉(拋出 ConcurrentModificationException 異常),所以這里我們是采用了類似于安全失敗的機制琳袄,即先創(chuàng)建一個新的 List江场,將原 List 內(nèi)的元素拷貝過來,再添加新的元素窖逗,最后再將原 List 指向新 List 即可址否。
如果此時容器未開始創(chuàng)建 Bean 對象,也就是正常啟動流程的話碎紊,那么就會進(jìn)入到第二個語句塊佑附,直接將 BeanDefinition 添加到 BeanDefinitionMap 中。
將 BeanName 添加到 BeanDefinitionNames List 當(dāng)中仗考,注冊流程完成音同。
refresh方法
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
//通過debugger可知,方法執(zhí)行到這里秃嗜,原始的configuration類被替換成了cglib的代理類 this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
一直一步一步debugger,重點來到了 因為這個方法實在實在是太長了太復(fù)雜了权均,我自己 Debug 跟了幾次顿膨,發(fā)現(xiàn)上下的許多代碼跟當(dāng)前分析的這個 @Configuration 都是沒有什么關(guān)系的,因此我就都省略掉了叽赊,我們只關(guān)注重點的實現(xiàn)代碼恋沃,在這里最重要的兩個方法一個是 invokeBeanDefinitionRegistryPostProcessors,另一個就是 invokeBeanFactoryPostProcessors必指。
invokeBeanDefinitionRegistryPostProcessors 方法中對于 @Configuration 主要的作用就是將其 @Configuration 注解信息解析到它的 BeanDefinition 的 Attributes 當(dāng)中囊咏。
invokeBeanFactoryPostProcessors 方法的作用主要是對 BeanDefinition 中的 Attitudes 進(jìn)行判斷,選取全注解(Attributes 當(dāng)中的 configurationClass 所對應(yīng)的值為 full)類塔橡,將其 BeanDefinition 中的 beanClass 替換為 CGLIB 的代理類梅割。
invokeBeanDefinitionRegistryPostProcessors
因此下面我來以此介紹這兩個方法,首先是跟進(jìn) invokeBeanDefinitionRegistryPostProcessors 方法葛家,然后再跟進(jìn)它所調(diào)用的 postProcessBeanDefinitionRegistry 方法户辞。我們一步一步找到,最終定位到ConfigurationClassPostProcessor#processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList();
String[] candidateNames = registry.getBeanDefinitionNames();
String[] var4 = candidateNames;
int var5 = candidateNames.length;
for(int var6 = 0; var6 < var5; ++var6) {
String beanName = var4[var6];
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
} else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
if (!configCandidates.isEmpty()) {
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry)registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
HashSet alreadyParsed = new HashSet(configCandidates.size());
do {
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
}
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();
Iterator var12 = alreadyParsed.iterator();
while(var12.hasNext()) {
ConfigurationClass configurationClass = (ConfigurationClass)var12.next();
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
String[] var23 = newCandidateNames;
int var24 = newCandidateNames.length;
for(int var14 = 0; var14 < var24; ++var14) {
String candidateName = var23[var14];
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());
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory)this.metadataReaderFactory).clearCache();
}
}
}
invokeBeanFactoryPostProcessors
另一個比較重要的方法就是這個PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors 方法惦银,因此我們直接跟進(jìn)去咆课。
private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
Iterator var2 = postProcessors.iterator();
while(var2.hasNext()) {
BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var2.next();
postProcessor.postProcessBeanFactory(beanFactory);
}
}
然后調(diào)用ConfigurationClassPostProcessor#postProcessBeanFactory的方法,在這個方法內(nèi)部扯俱,調(diào)用this.enhanceConfigurationClasses(beanFactory);
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap();
String[] var3 = beanFactory.getBeanDefinitionNames();
int var4 = var3.length;
for(int var5 = 0; var5 < var4; ++var5) {
String beanName = var3[var5];
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
AnnotationMetadata annotationMetadata = null;
MethodMetadata methodMetadata = null;
if (beanDef instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition)beanDef;
annotationMetadata = annotatedBeanDefinition.getMetadata();
methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
}
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
AbstractBeanDefinition abd = (AbstractBeanDefinition)beanDef;
if (!abd.hasBeanClass()) {
boolean liteConfigurationCandidateWithoutBeanMethods = "lite".equals(configClassAttr) && annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata);
if (!liteConfigurationCandidateWithoutBeanMethods) {
try {
abd.resolveBeanClass(this.beanClassLoader);
} catch (Throwable var14) {
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), var14);
}
}
}
}
if ("full".equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" + beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
if (this.logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
this.logger.info("Cannot enhance @Configuration bean definition '" + beanName + "' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.");
}
configBeanDefs.put(beanName, (AbstractBeanDefinition)beanDef);
}
}
if (!configBeanDefs.isEmpty()) {
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
Iterator var16 = configBeanDefs.entrySet().iterator();
while(var16.hasNext()) {
Entry<String, AbstractBeanDefinition> entry = (Entry)var16.next();
AbstractBeanDefinition beanDef = (AbstractBeanDefinition)entry.getValue();
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
Class<?> configClass = beanDef.getBeanClass();
//這里就是生產(chǎn)代理class了
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (this.logger.isTraceEnabled()) {
this.logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
//替換掉之前的beanclass
beanDef.setBeanClass(enhancedClass);
}
}
}
}
在這個方法中主要就執(zhí)行了獲取 BeanDefinition 的 Attributes 中鍵為 ConfigurationClass 值為 full 的全注解類书蚪,并對其使用 CGLIB 進(jìn)行代理的過程。
(1)遍歷獲取所有的 BeanDefinition迅栅,獲取全注解類殊校,并將其添加到全注解類容器(configBeanDefs)中;
(2)遍歷 configBeanDefs 容器读存,取出全注解類为流,并使用 CGLIB 進(jìn)行代理;
(3)使用代理后的類來替換原始類(替換 BeanDefinition 中的 BeanClass)让簿;
到這里我們就已經(jīng)完成了對于 @Configuration 注解處理的大致代碼流程分析敬察。