spring @Configuration原理解析

環(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 注解處理的大致代碼流程分析敬察。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市尔当,隨后出現(xiàn)的幾起案子莲祸,更是在濱河造成了極大的恐慌,老刑警劉巖椭迎,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锐帜,死亡現(xiàn)場離奇詭異,居然都是意外死亡畜号,警方通過查閱死者的電腦和手機缴阎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來简软,“玉大人蛮拔,你說我怎么就攤上這事述暂。” “怎么了语泽?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵贸典,是天一觀的道長视卢。 經(jīng)常有香客問我踱卵,道長,這世上最難降的妖魔是什么据过? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任惋砂,我火速辦了婚禮,結(jié)果婚禮上绳锅,老公的妹妹穿的比我還像新娘西饵。我一直安慰自己,他們只是感情好鳞芙,可當(dāng)我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布眷柔。 她就那樣靜靜地躺著,像睡著了一般原朝。 火紅的嫁衣襯著肌膚如雪驯嘱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天喳坠,我揣著相機與錄音鞠评,去河邊找鬼。 笑死壕鹉,一個胖子當(dāng)著我的面吹牛剃幌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晾浴,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼负乡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了脊凰?” 一聲冷哼從身側(cè)響起抖棘,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎笙各,沒想到半個月后钉答,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡杈抢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年数尿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惶楼。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡右蹦,死狀恐怖诊杆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情何陆,我是刑警寧澤晨汹,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站贷盲,受9級特大地震影響淘这,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜巩剖,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一铝穷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧佳魔,春花似錦曙聂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至贤姆,卻和暖如春榆苞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背庐氮。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工语稠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人弄砍。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓仙畦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親音婶。 傳聞我的和親對象是個殘疾皇子慨畸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,724評論 2 351