Spring中的@Configuration注解你真的了解吗?

环境:Springboot2.3.12.RELEASE


关于使用@Configuration注解后为何 类内部使用@Bean注解方法声明的方法在多次调用后会是返回相同的实例?

1 示例

如下:

 @Configuration
 public class BeanConfig {
     
     @Bean
     public Date date() {
         CustomerDAO c1 = customer() ;
         CustomerDAO c2 = customer() ;
         System.out.println("c1 = " + c1) ;
         System.out.println("c2 = " + c2) ;
         return new Date() ;
     }
     
     @Bean
     public CustomerDAO customer() {
         return new CustomerDAO() ;
     }
     
 }

输出:

 c1 = com.pack.config.CustomerDAO@1c0cf193
 c2 = com.pack.config.CustomerDAO@1c0cf193

将上面的@Configuration注解换成@Component后再次运行:

 c1 = com.pack.config.CustomerDAO@7b7e4b20
 c2 = com.pack.config.CustomerDAO@5ac0bf84

多个实例。

2 原理

使用@Configuration注解的类会为何会保证多次方法的调用返回的是同一个实例?

2.1 创建Spring上下文

创建上下文最核心的就是注册了一个BeanFactory处理器

 public class SpringApplication {
     public ConfigurableApplicationContext run(String... args) {
         ConfigurableApplicationContext context = null;
         context = createApplicationContext();
     }
     protected ConfigurableApplicationContext createApplicationContext() {
         return this.applicationContextFactory.create(this.webApplicationType);
     }
 }

跟踪createApplicationContext方法

 public class SpringApplication {
     protected ConfigurableApplicationContext createApplicationContext() {
         return this.applicationContextFactory.create(this.webApplicationType);
     }
 }

进入ApplicationContextFactory

 public interface ApplicationContextFactory {
     ApplicationContextFactory DEFAULT = (webApplicationType) -> {
         try {
             switch (webApplicationType) {
             case SERVLET:
                 // 当前是基于SERVLET容器的,所以创建下面这个实例
                 return new AnnotationConfigServletWebServerApplicationContext();
             case REACTIVE:
                 return new AnnotationConfigReactiveWebServerApplicationContext();
             default:
                 return new AnnotationConfigApplicationContext();
             }
         }
     };
 }

进入AnnotationConfigServletWebServerApplicationContext

 public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
         implements AnnotationConfigRegistry {
     public AnnotationConfigServletWebServerApplicationContext() {
         this.reader = new AnnotatedBeanDefinitionReader(this);
         this.scanner = new ClassPathBeanDefinitionScanner(this);
     }
 }

进入AnnotatedBeanDefinitionReader构造方法

 public class AnnotatedBeanDefinitionReader {
     public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
         this(registry, getOrCreateEnvironment(registry));
     }
     public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
         this.registry = registry;
         this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
         // 核心方法,这里非常重要,会注册系统的一些处理器
         AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
     }
 }

进入AnnotationConfigUtils#registerAnnotationConfigProcessors方法

 public abstract class AnnotationConfigUtils {
     public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
         registerAnnotationConfigProcessors(registry, null);
     }
 }

进入AnnotationConfiguUtils#registerAnnotationConfigProcessors方法

 public class AnnotationBeanDefinitionReader {
     public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
             "org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
     public static Set registerAnnotationConfigProcessors(
             BeanDefinitionRegistry registry, @Nullable Object source) {
         // ...
         // 判断当前上下文中是否有internalConfigurationAnnotationProcessor
         // 没有则注册专门用来处理@Configuration注解的
         // ConfigurationClassPostProcessor处理器
         if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
             RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
             def.setSource(source);
             beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
         }
         // ...
         return beanDefs;
     }
 }

以上在创建Spring上下文对象的时候注册了一个非常核心的处理器ConfigurationClassPostProcessor该类会处理带有@Configuration注解的类。

2.2 执行处理器

这里就会执行上一步中注册的BeanFactoryPostProcessor

上面注册的ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口

 public class SpringApplication {
     public ConfigurableApplicationContext run(String... args) {
         ConfigurableApplicationContext context = null;
         context = createApplicationContext();
         // 刷新上下文
         refreshContext(context);
     }
 }

跟踪refreshContext方法,进入到如下代码执行

 public abstract class AbstractApplicationContext extends DefaultResourceLoader
         implements ConfigurableApplicationContext {
     public void refresh() throws BeansException, IllegalStateException {
         synchronized (this.startupShutdownMonitor) {
             // ...
             // 执行BeanFactoryPostProcessor中的回调方法
             invokeBeanFactoryPostProcessors(beanFactory);
             // ...
         }
     }
 }

进入invokeBeanFactoryPostProcessors方法

 public abstract class AbstractApplicationContext extends DefaultResourceLoader
         implements ConfigurableApplicationContext {
     protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
         PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
     }
 }

进入invokeBeanfactoryPostProcessors方法

注意ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor也实现了BeanFactoryPostProcessor接口,这里方法的执行是会先执行BeanDefinitionRegistryPostProcessor的回调方法,最后再执行BeanFactoryPostProcessor中的回调方法。

执行流程为:

  1. ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
  2. 该方法主要左右通过方法名称也能猜到处理并注册当前CLASSPATH下的所有类中符合条件的Bean。
  3. ConfigurationClassPostProcessor#postProcessBeanFactory
  4. 该方法的作用
 final class PostProcessorRegistrationDelegate {
     public static void invokeBeanFactoryPostProcessors(
             ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
         // ...
         // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
         // 执行ConfigurationClassPostProcessor#postProcessBeanFactory方法
         invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
         invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
     }
     private static void invokeBeanFactoryPostProcessors(
             Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
         // 执行ConfigurationClassPostProcessor中的回调
         for (BeanFactoryPostProcessor postProcessor : postProcessors) {
             postProcessor.postProcessBeanFactory(beanFactory);
         }
     }
 }

进入ConfigurationClassPostProcessor#postProcessBeanFactory方法

 public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
 PriorityOrdered, ResourceLoaderAware, 
 ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware {
     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
         // 增强配置类
         enhanceConfigurationClasses(beanFactory);
         beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
     }
 }

2.3 增强配置类

接着上面进入enhanceConfigurationClasses方法

 public class ConfigurationClassPostProcessor {
     public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
         Map configBeanDefs = new LinkedHashMap<>();
         // 遍历当前上下文中注册的所有BeanDefinition集合,找到所有的配置类
         // 这里会就会找到两个,一个是启动类,一个是上面示例中的配置类BeanConfig
         for (String beanName : beanFactory.getBeanDefinitionNames()) {
             BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
             // ...
             configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
         }
         if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
             // nothing to enhance -> return immediately
             enhanceConfigClasses.end();
             return;
         }
 
         ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
         // 遍历找到所有的@Configuration配置类
         for (Map.Entry 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();
             // 这里就将BeanConfig配置类进行创建代理
             Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
             if (configClass != enhancedClass) {
                 beanDef.setBeanClass(enhancedClass);
             }
         }
     }
 }

进入ConfigurationClassEnhancer#enhance方法

 class ConfigurationClassEnhancer {
 
     // The callbacks to use. Note that these callbacks must be stateless.
     private static final Callback[] CALLBACKS = new Callback[] {
             new BeanMethodInterceptor(),
             new BeanFactoryAwareMethodInterceptor(),
             NoOp.INSTANCE
     };
     private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
     public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
         if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
             return configClass;
         }
         // 创建代理类
         Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
         return enhancedClass;
     }
     private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
         Enhancer enhancer = new Enhancer();
         enhancer.setSuperclass(configSuperClass);
         enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
         enhancer.setUseFactory(false);
         enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
         enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
         // 这里就是设置代理类执行的方法拦截器
         // 最核心的就是上面的BeanMethodInterceptor类
         enhancer.setCallbackFilter(CALLBACK_FILTER);
         enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
         return enhancer;
     }
 }

进入BeanMethodInterceptor

 private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
     public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
                             MethodProxy cglibMethodProxy) throws Throwable {
 
         // ... 
         // 该方法中就是从Spring容器中获取当前的Bean
         return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
     }
 }

进入resolveBeanReference方法

 class ConfigurationClassEnhancer {
     private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
                 ConfigurableBeanFactory beanFactory, String beanName) {
         Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
                         beanFactory.getBean(beanName));
         return beanInstance ;
     }
 }

完毕!!!

求个关注+转发
Spring 自定义Advisor以编程的方式实现AOP
SpringBoot WebFlux整合Spring Security进行权限认证
Springboot Security 基础应用 (1)
Springboot中Redis事务的使用及Lua脚本
SpringCloud Feign实现原理源分析
Spring Cloud全链路追踪SkyWalking及整合Elasticsearch
Spring Cloud 微服务日志收集管理Elastic Stack完整详细版
Spring Cloud链路追踪zipkin及整合Elasticsearch存储
Spring Cloud Gateway应用详解2内置过滤器
Spring通过源码分析了解这3种Bean处理器的执行过程
SpringBoot集群环境下使用Redis实现Session共享

Spring中的@Configuration注解你真的了解吗?

Spring中的@Configuration注解你真的了解吗?

Spring中的@Configuration注解你真的了解吗?

展开阅读全文

页面更新:2024-04-25

标签:注解   遍历   上下文   示例   文中   容器   处理器   实例   核心   方法

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top