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 中的回调方法。
执行流程为: ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 该方法主要左右通过方法名称也能猜到处理并注册当前CLASSPATH下的所有类中符合条件的Bean。 ConfigurationClassPostProcessor#postProcessBeanFactory 该方法的作用 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共享