spring @Configuration原理解析

环境版本:java8,spring5.2.x,maven3.6
@Configuration注册类的全过程,话不多说,上代码,我这里是从关键的方法人手了


 private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
         //1, 为我们传入的class创建bean的定义
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
        // 2. 判断当前类是否应当跳过(根据 @Conditional 判断)
        if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            abd.setInstanceSupplier(supplier);
            // 3. 从类元数据中解析获取 scope 作用范围信息(默认为 singleton)
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
            //4,为改bean定义设置作用范围           
            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. 创建 BeanDefinition 的 BeanDefinitionHolder
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
            // 7. 应用 ScopedProxyMode
            definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            // 8. 注册 BeanDefinition          
            BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
        }
    }

说明:
doRegisterBean方法很复杂,我们的主题是@Configuration,所以省略一些不重要的代码。

  • 为我们传入的 class 创建对应的 BeanDefinition 并进行相关默认值的初始化,这里的 BeanDefinition 指的是 AnnotatedGenericBeanDefinition,它是 GenericBeanDefinition 的子类,主要添加了对注解元数据的支持(这点通过下面的构造器代码也能够看出来,它将类元数据 metadata 单独进行保存,这个 StandardAnnotationMetadata 中有一个属性 annotations 就是用来专门保存类的注解信息的)。
    public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
        this.setBeanClass(beanClass);
        this.metadata = AnnotationMetadata.introspect(beanClass);
    }
  • 根据 @Conditional 注解来判断当前 Bean 实例化是否需要跳过(即当前不满足 @Conditional 注解条件)。
     public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
        return this.shouldSkip(metadata, (ConfigurationPhase)null);
     }
  • 将获取到的 scope 赋值给 BeanDefinition(这步完成后刚刚创建的 AnnotatedGenericBeanDefinition 对象的 scope 属性为 scope 值)。

  • 获取并处理类的通用注解(@Lazy、@Primary、@DependsOn、@Role 和 @Description)信息,这里调用的是 processCommonDefinitionAnnotations 方法,这个方法没有什么太大营养,就是把你的类元数据中的注解信息取出来,然后依次检查是否设置了对应的注解,并将值赋给刚刚创建的 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"));
        }

    }
  • 创建 BeanDefinition 对应的 BeanDefinitionHolder 对象,这个对象没什么太多特殊的作用,就是持有一个 BeanDefinition 对象。

  • 接下里调用 applyScopedProxyMode 方法来应用(创建)一个 ScopedProxyMode 对象(跟 @Configuration 无关,所以不去过细分析)。

  • 最后一步,也就是最重要的注册 BeanDefinition 到 BeanDefinitionMap 中,这里直接进方法看代码。

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 的主名称进行注册,这个主名称其实就是我们的 Bean 名称(当前的名称就是我们刚刚传入的配置类的类名 SpringConfig),然后又使用了标签进行注册,这里我们先不考虑标签,所以直接使用 Bean 名称进行注册,继续跟进 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. 如果当前的 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);
      //两个分支-> 如果容器中已经存在了该 BeanName 所对应的 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 所对应的的 BeanDefinition
       else {
            //13. 判断当前工厂是否已经开始创建 Bean 对象
            if (this.hasBeanCreationStarted()) {
                synchronized(this.beanDefinitionMap) {
                     // 将该 BeanDefinition 添加到 Map 中
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    //// 按照原始 BeanName List 大小 +1 创建新 BeanName List
                    List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
// 将原始 BeanName List 内容复制到新 BeanName List 中                  updatedDefinitions.addAll(this.beanDefinitionNames);
                    // 将新添加的 BeanName 添加到新的 BeanName List 中
                    updatedDefinitions.add(beanName);
                     // 让原始的 BeanName List 指向新 BeanName List
                    this.beanDefinitionNames = updatedDefinitions;
                     // 移除工厂内部的手动单例名称集
                    this.removeManualSingletonName(beanName);
                }
            } else {
                 // 14. 没有正在创建bean,将 BeanDefinition 直接添加到 Map 中
                this.beanDefinitionMap.put(beanName, beanDefinition);
                 // 15. 如果非正在创建则直接将 BeanName 添加到 BeanName List 中
                this.beanDefinitionNames.add(beanName);
                 // 从 manualSingletonNames 移除 BeanName
                this.removeManualSingletonName(beanName);
            }

            this.frozenBeanDefinitionNames = null;
        }
         // 如果 Map 中已存在 BeanName 对应的 BeanDefinition 或者 BeanName 为单例模式
        if (existingDefinition == null && !this.containsSingleton(beanName)) {
            if (this.isConfigurationFrozen()) {
                this.clearByTypeCache();
            }
        } else {
             // 重置 BeanName 在容器中对应的 BeanDefinition
            this.resetBeanDefinition(beanName);
        }
 }
  • 验证 BeanName 和 BeanDefinition 不为空。

  • 然后判断当前的 BeanDefinition 是否是 AbstractBeanDefinition 的子类,如果是的话就调用 prepareMethodOverrides 方法就对其抽象方法进行验证,判断这个 BeanDefinition 是否正确重写了它的抽象方法。

  • 接着判断当前容器中是否已经存在 BeanName 所对应的 BeanDefinition(BeanDefinition 存储于 BeanDefinitionMap 中,键为 BeanName,值为 BeanDefinition),如果已经存在就判断是否可以进行替换等一系列逻辑,如果不存在就进入 else 语句块。

  • 接着调用 hasBeanCreationStarted 判断当前工厂是否已经开始创建 Bean(这个方法里面主要是通过判断 alreadyCreated 容器内是否为空,因为当工厂将要实例化创建一个 Bean 对象的时候都会先将其存放在这个 alreadyCreated 容器中),如果此时工厂还未开始创建 Bean 对象,那么我们就可以直接将当前的 BeanName 和 BeanDefinition 直接添加到容器中。但是如果此时工厂已经开始创建 Bean 对象了(根据 BeanDefinition),那么正如它注释中所讲这个时候再对 BeanDefinitionMap 和 BeanDefinitionNames 来进行操作就是不安全的了,因此这个时候我们就需要通过加锁来保证整个的添加操作线程安全。但是在什么情况下会出现这个问题呢,显然如果我们按照正常的代码逻辑到目前为止还没有进行任何的 Bean 的创建工作,但是假如在我们自己的业务代码中,在另一个线程中,当容器开始创建 Bean 对象时,我们直接获取到容器中的这个 DefaultListableBeanFactory,并调用这个 registerBeanDefinition 方法对其当中的 BeanDefinitionMap 进行添加或删除等修改操作,那么就会造成非线程安全的问题(这里的安全问题主要是指虽然 BeanDefinitionMap 是 concurrentHashMap 的线程安全 Map,对于将 BeanDefinition 添加到其中的操作时线程安全的,但是我们无法保证 BeanDefinitionName 和 BeanDefinition 能够同时被分别添加到两个容器中(非原子操作),即整个操作流程是非线程安全的)。并且还可以注意到在下面的 BeanDefinitionNames 这个 List 当中顺序保存了所有的 BeanName,在锁的过程中我们锁的是 BeanDefinitionMap 这个对象,并没有锁住这个 BeanDefinitionNames,因此跟上面一样的道理,假如有其他的线程正在容器中遍历读取 BeanDefinitionNames List 当中的信息对 List 当中的 Bean 进行实例化,那么此时我们在当前线程对 BeanDefinitionNames List 直接进行添加操作会引发快速失败(抛出 ConcurrentModificationException 异常),所以这里我们是采用了类似于安全失败的机制,即先创建一个新的 List,将原 List 内的元素拷贝过来,再添加新的元素,最后再将原 List 指向新 List 即可。

  • 如果此时容器未开始创建 Bean 对象,也就是正常启动流程的话,那么就会进入到第二个语句块,直接将 BeanDefinition 添加到 BeanDefinitionMap 中。

  • 将 BeanName 添加到 BeanDefinitionNames List 当中,注册流程完成。

refresh方法

 public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                //通过debugger可知,方法执行到这里,原始的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,重点来到了 因为这个方法实在实在是太长了太复杂了,我自己 Debug 跟了几次,发现上下的许多代码跟当前分析的这个 @Configuration 都是没有什么关系的,因此我就都省略掉了,我们只关注重点的实现代码,在这里最重要的两个方法一个是 invokeBeanDefinitionRegistryPostProcessors,另一个就是 invokeBeanFactoryPostProcessors。

  • invokeBeanDefinitionRegistryPostProcessors 方法中对于 @Configuration 主要的作用就是将其 @Configuration 注解信息解析到它的 BeanDefinition 的 Attributes 当中。

  • invokeBeanFactoryPostProcessors 方法的作用主要是对 BeanDefinition 中的 Attitudes 进行判断,选取全注解(Attributes 当中的 configurationClass 所对应的值为 full)类,将其 BeanDefinition 中的 beanClass 替换为 CGLIB 的代理类。

invokeBeanDefinitionRegistryPostProcessors

因此下面我来以此介绍这两个方法,首先是跟进 invokeBeanDefinitionRegistryPostProcessors 方法,然后再跟进它所调用的 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 方法,因此我们直接跟进去。

   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);
        }

    }

然后调用ConfigurationClassPostProcessor#postProcessBeanFactory的方法,在这个方法内部,调用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();
                //这里就是生产代理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);
                }
            }

        }
    }

在这个方法中主要就执行了获取 BeanDefinition 的 Attributes 中键为 ConfigurationClass 值为 full 的全注解类,并对其使用 CGLIB 进行代理的过程。

(1)遍历获取所有的 BeanDefinition,获取全注解类,并将其添加到全注解类容器(configBeanDefs)中;

(2)遍历 configBeanDefs 容器,取出全注解类,并使用 CGLIB 进行代理;

(3)使用代理后的类来替换原始类(替换 BeanDefinition 中的 BeanClass);

到这里我们就已经完成了对于 @Configuration 注解处理的大致代码流程分析。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266