环境:Springboot2.3.12.RELEASE
关于使用@Configuration注解后为何 类内部使用@Bean注解方法声明的方法在多次调用后会是返回相同的实例?
如下:
@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
多个实例。
使用@Configuration注解的类会为何会保证多次方法的调用返回的是同一个实例?
创建上下文最核心的就是注册了一个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注解的类。
这里就会执行上一步中注册的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中的回调方法。
执行流程为:
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));
}
}
接着上面进入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共享
页面更新:2024-04-25
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号