Spring源码解析之@Configuration

Posted 热心市民小陈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码解析之@Configuration相关的知识,希望对你有一定的参考价值。

@Configuration简介

用于标识一个类为配置类,与xml配置效果类似

用法简介

public class TestApplication {

    public static void main(String args[]) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

    }
}

@Configuration
public class AppConfig {

    @Bean
    public A a(){
        return new A();
    }
    @Bean
    public B b(){
        return new B();
    }
} 




public class A {

    public A(){
        System.out.println("Call A constructor");
    }
}



public class B {

    public B(){
        System.out.println("Call B constructor");
    }
}

上面的例子应该是@Configuration最普遍一种使用场景了,在@Configuration class下面配置@Bean method,用于想Spring Ioc容器注入bean.但其实我们把AppConfig的@Configuration注解去掉,对应的Bean也是可以被注入到容器中去的。

那么问题来了@Configuration到底有什么作用?

我们给AppConfig改写一下,如下:

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {

   @Bean
   public A a(){
      b();
      return new A();
   }
   @Bean
   public B b(){
      return new B();
   }

再去执行TestApplication#main,那么执行结果会是什么样呢?

Call A constructor
Call B constructor

嗯哼?按照Java的语法,B的构造函数应该是被调用了两次啊?为什么只有输出一句Call B constructor?

这其实就是@Configuration再发挥作用啦,不信你去掉@Configuration,再去运行一下,就会发现B的构造函数被执行了两次。

官方给出了这样一段解释对于被@Configuration注解的类

In common scenarios,@Beanmethods are to be declared within@Configurationclasses, ensuring that “full” mode is always used and that cross-method references therefore get redirected to the container’s lifecycle management.

在一般情况下,@Bean method 是被声明在@Configuration类中的,以确保 full mode总是被使用,并且跨方法的引用会被重定向到容器生命周期管理。

怎么理解呢?

原来Spring将被@Configuration注解的配置类定义为full configuration, 而将没有被@Configuration注解的配置类定义为lite configuration。full configuration能重定向从跨方法的引用,从而保证上述代码中的b bean是一个单例.

源码中是如何实现@Configuration语意

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
   /**
    * 调用无参构造函数,实例化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
    * 同时会调用父类GenericApplicationContext无参构造函数实例化一个关键的工厂DefaultListableBeanFactory
    * 同时还会注册一些开天辟地的后置处理器到beanDefinitionMap,这些后置处理器有bean工厂后置处理器;有bean后置处理器
    */
   this();
   //将componentClasses注册到beanDefinitionMap集合中去
   register(componentClasses);
  
   refresh();
}

跟踪refresh()

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         //供上下文(Context)子类继承,允许在这里后置处理bean factory
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         //按顺序调用BeanFactoryPostProcessor,这里的按顺序仅实现了PriorityOrdered和Ordered的语意,未实现@Order注解的语意
         //通过调用ConfigurationConfigPostProcessor#postProcessBeanDefinitionRegistry
         //解析@Configuration配置类,将自定义的BeanFactoryPostProcessor、BeanPostProcessor注册到beanDefinitionMap
         //接着实例化所有(包括开天辟地)的BeanFactoryPostProcessor,然后再调用BeanFactoryPostProcessor#postProcessBeanFactory
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         //按顺序将BeanPostProcessor实例化成bean并注册到beanFactory的beanPostProcessors,
         //这里的按顺序仅实现了PriorityOrdered和Ordered的语意,未实现@Order注解的语意
         //因为BeanPostProcessor要在普通bean初始化()前后被调用,所以需要提前完成实例化并注册到beanFactory的beanPostProcessors
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         //注册国际化相关的Bean
         initMessageSource();

         // Initialize event multicaster for this context.
         //为上下文注册应用事件广播器(用于ApplicationEvent的广播),如果有自定义则使用自定义的,如果没有则内部实例化一个
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         //注册所有(静态、动态)的listener,并广播earlyApplicationEvents
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         //实例化用户自定义的普通单例Bean(非开天辟地的、非后置处理器)
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // Propagate exception to caller.
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}

跟踪invokeBeanFactoryPostProcessors(beanFactory)

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
   // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}

跟踪invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();

        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }

            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the bean factory post-processors apply to them!
            // Separate between BeanDefinitionRegistryPostProcessors that implement
            // PriorityOrdered, Ordered, and the rest.
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            //此处调用ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry,
            //解析配置类,为配置中的bean定义生成对应beanDefinition,并注入到registry的beanDefinitionMap
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            //调用ConfigurationClassPostProcessor#postProcessBeanFactory增强配置类(通过cglib生成增强类,load到jvm内存,
            //设置beanDefinition的beanClass为增强类)
            //为什么要增强配置类?主要是为了让@Bean生成的bean是单例,
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // Finally, invoke all other BeanFactoryPostProcessors.
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }

跟踪invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);

private static void invokeBeanFactoryPostProcessors(
      Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

   for (BeanFactoryPostProcessor postProcessor : postProcessors) {
      postProcessor.postProcessBeanFactory(beanFactory);
   }
}

跟踪ConfigurationClassPostProcessor#postProcessBeanFactory

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   int factoryId = System.identityHashCode(beanFactory);
   if (this.factoriesPostProcessed.contains(factoryId)) {
      throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + beanFactory);
   }
   this.factoriesPostProcessed.add(factoryId);
   if (!this.registriesPostProcessed.contains(factoryId)) {
      // BeanDefinitionRegistryPostProcessor hook apparently not supported...
      // Simply call processConfigurationClasses lazily at this point then.
      processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
   }
   //为@Configuration注解的类生成增强类(如果有必要),并替换bd中的beanClass属性,
   enhanceConfigurationClasses(beanFactory);
   beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

到了这一步谜底几乎已经揭晓了,@Configuration class是通过增强来实现它的语义的。通过增强把跨方法的引用调用重定向到Spring生命周期管理.我们近一步探索下这个enhanceConfigurationClasses方法

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
   Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
   for (String beanName : beanFactory.getBeanDefinitionNames()) {
      BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
      Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
      MethodMetadata methodMetadata = null;
      if (beanDef instanceof AnnotatedBeanDefinition) {
         methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
      }
      if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
         // Configuration class (full or lite) or a configuration-derived @Bean method
         // -> resolve bean class at this point...
         AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
         if (!abd.hasBeanClass()) {
            try {
               abd.resolveBeanClass(this.beanClassLoader);
            }
            catch (Throwable ex) {
               throw new IllegalStateException(
                     "Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
            }
         }
      }
      //在ConfigurationClassUtils.checkConfigurationClassCandidate方法中会标记Configuration is full or lite
      if (ConfigurationClassUtils.CONFIGURATION_CLASS_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");
         }
         else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
            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()) {
      // nothing to enhance -> return immediately
      return;
   }

   ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
   for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
      AbstractBeanDefinition beanDef = entry.getValue();
      // If a @Configuration class gets proxied, always proxy the target class
      beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
      // Set enhanced subclass of the user-specified bean class
      Class<?> configClass = beanDef.getBeanClass();
      //为@Configuration注解的类生成增强类
      Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
      if (configClass != enhancedClass) {
         if (logger.isTraceEnabled()) {
            logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
                  "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
         }
         beanDef.setBeanClass(enhancedClass);
      }
   }
}

看到有那么一句话Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);

很明显了,使用cglib技术为config class生成一个enhancedClass,再通过beanDef.setBeanClass(enhancedClass);修改beanDefinition的BeanClass属性,在bean实例化阶段,会利用反射技术将beanClass属性对应的类实例化出来,所以最终实例化出来的@Configuration bean是一个代理类的实例。这里稍微提一下为什么要使用cglib,而不是jdk动态代理,主要是因为jdk动态代理是基于接口的,而这里AppConfig并没有实现任何接口,所以必须用cglib技术。

总结

被@Configuration 注解的类,是 full configuration class,该类会被增强(通过cglib),从而实现跨方法引用调用被重定向到Spring 生命周期管理,最终保证@Bean method生成的bean是一个单例。

以上是关于Spring源码解析之@Configuration的主要内容,如果未能解决你的问题,请参考以下文章

spring源码之@Import

Spring框架源码 @configuration源码深度解析

[Spring6.0源码解析]简述@Configuration注解

Spring源码解析 – @Configuration配置类及注解Bean的解析

Mybatis之Configuration初始化(配置文件.xml的解析)

Spring之@Configuration配置解析