篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Spring 6.0源码解析] @Configuration注解源码解析相关的知识,希望对你有一定的参考价值。
Spring 6.0源码解析之@Configuration
首先写一个启动代码:
public class ConfigurationAnnotationTest
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationAnnotationTest.class);
public static void main(String[] args)
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigurationAnnotationConfig.class);
ConfigurationAnnotationConfig config = context.getBean(ConfigurationAnnotationConfig.class);
Person person1 = config.person();
Person person2 = config.person();
LOGGER.info("person1 是否等于 person2 ===>> ", (person1 == person2));
用 @Configuration 注解的配置类如下:
@Configuration
public class ConfigurationAnnotationConfig
@Bean
public Person person()
return new Person();
从上述代码中可以看到,我们通过AnnotationConfigApplicationContext类来为配置类加载Spring应用上下文,创建IOC容器。
所以就从AnnotationConfigApplicationContext类从手,来分析 @Configuration 注解加载的有关源码。
为了方便分析,先放一张 AnnotationConfigApplicationContext 类的 UML 图在这里。
一、注册 ConfigurationClassPostProcessor 源码分析
ConfigurationClassPostProcessor
是Spring
中最重要的后置处理器。@Configuration
注解解析涉及到了 ConfigurationClassPostProcessor
类的注册流程。
从启动代码中可以看到,使用了 AnnotationConfigApplicationContext
类的构造方法传入了配置类 ConfigurationAnnotationConfig
,来创建了 IOC
容器,那么我们就以此为入口进行分析。
使用的 AnnotationConfigApplicationContext
类构造方法如下:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigurationAnnotationConfig.class);
- 进入该构造方法:
public AnnotationConfigApplicationContext(Class<?>... componentClasses)
this();
register(componentClasses);
refresh();
可以看到,在上述构造方法中,先调用了 AnnotationConfigApplicationContext
类的无参构造方法 this()
。
- 分析这个 this(),源码如下:
public AnnotationConfigApplicationContext()
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this);
在 AnnotationConfigApplicationContext
的无参构造函数中,主要做了这些事情:
- 实例化
AnnotatedBeanDefinitionReader
类的成员变量 reader
。reader
主要是为了解析带有注解的 Bean 的 BeanDefinition
,并将其注册到 Bean
工厂中。
- 实例化
ClassPathBeanDefinitionScanner
类的成员变量 scanner
。scanner
会扫描指定包下的类,并将符合过滤条件的类注册到IOC
容器内。
注:StartupStep
接口主要作用是为了跟踪应用程序的启动顺序。
分析实例化 reader
这个成员变量的代码,也就是如下代码片段:
this.reader = new AnnotatedBeanDefinitionReader(this);
- 调用了
AnnotatedBeanDefinitionReader
的构造方法:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)
this(registry, getOrCreateEnvironment(registry));
- 其中又调用了
AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)
构造方法,源码如下:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
在该构造方法中,最重要的就是最后一句代码 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
,将 BeanDefinitionRegistry
类型的registry
传入使用。通过前面的代码跟踪可知,this.registry
对象的本质是 AnnotationConfigApplicationContext
类对象的实例。
注:根据上文 AnnotationConfigApplicationContext
类的 UML
图可得知,AnnotationConfigApplicationContext
类继承了 GenericApplicationContext
,GenericApplicationContext
类 又实现了BeanDefinitionRegistry
接口。
- 分析
AnnotationConfigUtils
调用的 registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)
方法,源码如下:
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)
registerAnnotationConfigProcessors(registry, null);
- 继续分析调用的
registerAnnotationConfigProcessors
方法,这个方法的源码很长,省略部分源码,如下:
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source)
// ....省略其他代码....
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
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;
这里只展示了这个方法中涉及到的 ConfigurationClassPostProcessor
类注册到IOC的相关代码。
可以看到,调用了 registerPostProcessor
方法,从方法名就可以看出,注册后置处理器。进入这个方法。
registerPostProcessor
方法的源码如下:
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName)
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
可以看到,调用了 registry 参数的 registerBeanDefinition
方法来注册了 ConfigurationClassPostProcessor
。
代码跟踪到这里,先来整理一下思路。从上面的整条链路上来看,registry 参数实际上就是 AnnotationConfigApplicationContext
类的实例,definition 参数实际上是带着 ConfigurationClassPostProcessor
类的 RootBeanDefinition
实例。
- 进入注册方法
registerBeanDefinition
,源码如下:
public interface BeanDefinitionRegistry extends AliasRegistry
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
// .....
是调用了BeanDefinitionRegistry
接口的registerBeanDefinition
方法。
在之前的 UML
图中可以知道,AnnotationConfigApplicationContext
类继承了 GenericApplicationContext
,GenericApplicationContext
类 又实现了BeanDefinitionRegistry
接口,所以跳转到GenericApplicationContext
类的实现。
- 源码如下:
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
可以看到,实际上是调用了 DefaultListableBeanFactory
类的 registerBeanDefinition
方法。this.beanFactory
是 DefaultListableBeanFactory
类的实例。
- 分析
DefaultListableBeanFactory
类的 registerBeanDefinition
方法,主要源码如下:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException
// ... 省略其他代码 ...
BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (existingDefinition != null)
// ... 省略其他代码 ...
this.beanDefinitionMap.put(beanName, beanDefinition);
else
// ... 省略其他代码 ...
this.beanDefinitionMap.put(beanName, beanDefinition);
// ... 省略其他代码 ...
// ... 省略其他代码 ...
通过这段代码可以看到,其实向 Spring
的 IOC
容器中注册Bean
,就是向beanDefinitionMap
对象中增加元素。beanDefinitionMap
对象的本质是一个 ConcurrentHashMap
对象:
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
key是beanName
的名字,value就是定义的Bean。在这里注册的就是 ConfigurationClassPostProcessor
类。
通过代码跟踪,我们可以知道在 AnnotationConfigApplicationContext
类的无参构造函数中,完成了 ConfigurationClassPostProcessor
类的注册。
那么到这里,涉及到的 ConfigurationClassPostProcessor
后置处理器的注册过程源码分析结束。
二、注册 @Configuration 配置类源码分析
从启动代码中可以看到,使用了 AnnotationConfigApplicationContext
类的构造方法传入了配置类 ConfigurationAnnotationConfig
,来创建了 IOC
容器。
调用的构造方法如下:
public AnnotationConfigApplicationContext(Class<?>... componentClasses)
this();
register(componentClasses);
refresh();
在之前已经分析过了 this()
构造函数方法,主要是完成了 后置处理器 ConfigurationClassPostProcessor
的注册,接下来分析 register
对配置类 ConfigurationAnnotationConfig
的注册。
- 进入
register(componentClasses)
方法:
@Override
public void register(Class<?>... componentClasses)
Assert.notEmpty(componentClasses, "At least one component class must be specified");
StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register").tag("classes", () -> Arrays.toString(componentClasses));
this.reader.register(componentClasses);
registerComponentClass.end();
主要代码是调动了 this.reader.register(componentClasses)
方法,传入了 componentClasses
进行注册。
- 分析
reader
对象的 register
方法。
注:reader
对象在这里就是 AnnotatedBeanDefinitionReader
的实例化对象
public void register(Class<?>... componentClasses)
for (Class<?> componentClass : componentClasses)
registerBean(componentClass);
在 register
方法中循环遍历传入的可变参数,每次循环都会调用 registerBean
方法。
- 分析
registerBean
方法
public void registerBean(Class<?> beanClass)
doRegisterBean(beanClass, null, null, null, null);
在 registerBean
中又调用了 doRegisterBean
方法。
- 分析
doRegisterBean
方法
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers)
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
// ... 省略其他代码 ...
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// ... 省略其他代码 ...
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
可以看到,主要是调用了 AnnotationConfigUtils.applyScopedProxyMode()
方法和 BeanDefinitionReaderUtils.registerBeanDefinition()
方法。
AnnotationConfigUtils
的applyScopedProxyMode
方法主要是为了解析 Bean 中的@Scope
注解,应用 @Scope注解中的 ProxyMode
属性。这里不做重点讲解。
- 主要解析
BeanDefinitionReaderUtils.registerBeanDefinition()
方法:
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException
String beanName = definitionHolder.getBeanName();
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);
可以看到,这边也使用了 registry
的 registerBeanDefinition
方法向 IOC
容器中注册了 Bean
。从上面的跟踪代码可知,调用 registry.registerBeanDefinition()
方法注册的 Bean
其实就是ConfigurationAnnotationConfig
配置类。
而这部分的注册源码逻辑与之前注册 ConfigurationClassPostProcessor
类的代码相同,同样是调用了 DefaultListableBeanFactory
类的 registerBeanDefinition
方法,不再重复分析。
至此我们可以看到,这部分就是对 ConfigurationAnnotationConfig
配置类的 Bean
进行了注册。
三、实例化流程源码分析
上面分析了注册 ConfigurationClassPostProcessor
后置处理器的源码与注册 ConfigurationAnnotationConfig
配置类的源码,接下来继续分析,Spring
IOC
容器在刷星时,会实例化 @Configuration
注解标注的类。
- 继续从这个构造函数开始:
public AnnotationConfigApplicationContext(Class<?>... componentClasses)
this();
register(componentClasses);
refresh();
可以看到,是调用了 refresh()
这个方法来刷新 Spring
IOC
容器。
- 进入
refresh()
方法:
@Override
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 预处理操作,包括初始化环境变量、处理系统属性、设置属性访问器等等
prepareRefresh();
// 调用 obtainFreshBeanFactory 方法获取一个新的 BeanFactory 对象,该对象用于保存所有 Bean 的定义信息和实例化对象。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// BeanFactory的准备工作
prepareBeanFactory(beanFactory);
try
// 是在对 bean 工厂进行准备以及初始化之后的一个补充处理,用于允许子类对 bean 工厂做一些自定义的处理,以满足特定的应用场景
// 当我们集成 AbstractApplicationContext 类时,可以通过重写 postProcessBeanFactory() 方法来进行自定义处理。
// 如果在这个方法中将某个 bean 的属性值修改了,那么在后面读取该 bean 的属性值时,就会读到被修改过的属性值。
// 总的来说, postProcessBeanFactory() 方法是一个非常灵活的扩展点,允许我们通过自定义的方式对 bean 工厂进行处理,从而实现一些特定的应用场景。
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 用于调用所有实现了 BeanFactoryPostProcessor 接口的类的 postProcessBeanFactory 方法
// 是执行处理 BeanFactoryPostProcessor 的核心方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注册BeanPostProcessor(Bean的后置处理器),用于拦截bean创建过程
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
initMessageSource();
// 初始化事件派发器
initApplicationEventMulticaster();
// 空方法,可以用于子类实现在容器刷新时自定义逻辑
onRefresh();
// 注册时间监听器,将所有项目里面的ApplicationListener注册到容器中来
registerListeners();
// 初始化所有剩下的单实例bean,单例bean在初始化容器时创建,原型bean在获取时(getbean)时创建
finishBeanFactoryInitialization(beanFactory);
// 完成BeanFactory的初始化创建工作,IOC容器就创建完成
finishRefresh();
// ... 省略部分代码 ...
refresh()
方法是在 AbstractApplicationContext
容器中实现的,里面做了很多的事情。
由上面的代码解析可以看出,在 refresh
方法中,invokeBeanFactoryPostProcessors
方法是执行处理 BeanFactoryPostProcessor
后置处理器的核心方法,在前面的解析中可知注册了 ConfigurationClassPostProcessor
后置处理器,所以这里重点关注 invokeBeanFactoryPostProcessors
的执行过程。
- 进入
invokeBeanFactoryPostProcessors
方法。
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 (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME))
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
其中又调用了 PostProcessorRegistrationDelegate
类的 invokeBeanFactoryPostProcessors
静态方法。
- 进入
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
方法
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors)
// 定义一个记录已经调用过的 BeanFactoryPostProcessor 的 Set,用于防止重复调用。
Set<String> processedBeans = new HashSet<>();
// ... 省略部分代码 ...
// 调用普通的 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
// ... 省略部分代码 ...
invokeBeanFactoryPostProcessors
方法主要用于调用 BeanFactoryPostProcessor
接口实现类的 postProcessBeanFactory
方法,处理 BeanFactory
。
如上代码可知,在该方法中又调用了 PostProcessorRegistrationDelegate
类的另一个 invokeBeanFactoryPostProcessors
方法。
- 进入
invokeBeanFactoryPostProcessors
方法:
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory)
for (BeanFactoryPostProcessor postProcessor : postProcessors)
StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanFactory(beanFactory);
postProcessBeanFactory.end();
可以看到,在该方法中会去遍历所有的 BeanFactoryPostProcessor
集合,并调用元素的 postProcessBeanFactory
方法,出传入 beanFactory
来实例化对象。
从上面的代码解析来看,这边调用的 BeanFactoryPostProcessor
接口实现类为 ConfigurationClassPostProcessor
类,所以调用实现的是 ConfigurationClassPostProcessor
类的 postProcessBeanFactory
方法。
- 解析
ConfigurationClassPostProcessor
类的 postProcessBeanFactory
方法。
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);
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
在 postProcessBeanFactory
方法中又调用了 enhanceConfigurationClasses
方法。
- 解析
enhanceConfigurationClasses
方法。
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory)
// ... 省略部分代码 ...
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();
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);
enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
可以看出这段代码中,主要是用 ConfigurationClassEnhancer
对象调用 enhance
方法来生成代理类,也就是使用 CGLib
生成代理类。
- 解析
enhance
方法。
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader)
if (EnhancedConfiguration.class.isAssignableFrom(configClass))
if (logger.isDebugEnabled())
logger.debug(String.format("Ignoring request to enhance %s as it has " +
"already been enhanced. This usually indicates that more than one " +
"ConfigurationClassPostProcessor has been registered (e.g. via " +
"<context:annotation-config>). This is harmless, but you may " +
"want check your configuration and remove one CCPP if possible",
configClass.getName()));
return configClass;
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
if (logger.isTraceEnabled())
logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
configClass.getName(), enhancedClass.getName()));
return enhancedClass;
可以看到调用了 createClass
方法,该方法用于创建代理类。在调用这个方法之前先调用了 newEnhancer
方法来实例化一个 Enhancer
对象。
- 先看
newEnhancer
方法。
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.setAttemptLoad(true);
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
newEnhancer
方法主要是用于生成 CGLib
动态代理 Enhancer
对象,后续会使用 Enhancer
对象生成代理类。
从源码中可以看出,newEnhancer
方法为要生成的代理类设置了父类和接口。
设置的接口是 EnhancedConfiguration
类,EnhancedConfiguration
类又继承了 BeanFactoryAware
接口,所以在之后,生成的代理类中可以调用 BeanFactoryAware
接口的 setBeanFactory
方法来获取到 beanFactory
对象。
- 接着来看
createClass
方法。
private Class<?> createClass(Enhancer enhancer)
// 创建代理类
Class<?> subclass = enhancer.createClass();
// Registering callbacks statically (as opposed to thread-local)
// is critical for usage in an OSGi environment (SPR-5932)...
Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
return subclass;
在 createClass
方法中,调用了 enhancer.createClass
方法创建了代理类。
enhancer.createClass
方法是CGLib
的方法,创建的代理类目标类的子类,所以这里创建出来的代理类是目标类的子类。
- 关注下
CALLBACKS
这个参数。
static final Callback[] CALLBACKS = new Callback[]
new BeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
;
可以看到 CALLBACKS
这个参数其实是个 Callback
类型的数组,数组中的每个元素都是 Callback
类型。同时 BeanMethodInterceptor
和 BeanFactoryAwareMethodInterceptor
类也是拦截器类型。
BeanMethodInterceptor
类实现了 MethodInterceptor
接口和 ConditionalCallback
接口,主要作用是对标注了 @Bean
的注解方法进行拦截,执行 intercept
方法来生成 Bean
的实例对象。
- 浅看一下
BeanMethodInterceptor
类的源码
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable
// ... 省略部分代码 ...
// 如果已经创建了 Bean 的代理实例对象,则调用父类的方法
if (isCurrentlyInvokedFactoryMethod(beanMethod))
// ... 省略部分代码 ...
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
// ... 省略部分代码 ...
上述代码可以保证在类上添加 @Configuration
注解后,只会为一个类生成一个代理对象,也就是能保证标注了 @Configuration
注解的类生成的代理类是单例模式的。
因为使用 CGLib
类创建出来的代理类是目标类的子类,所以第一次执行上述代码片段时,会调用 cglibMethodProxy.invokeSuper
方法执行父类,也就是执行目标类的方法。
第二次调用上述代码片段时,会调用 resolveBeanReference
方法。
13.最后再简单看下 resolveBeanReference
方法。只挑了重点需要看的地方。
private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
ConfigurableBeanFactory beanFactory, String beanName)
boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
try
// ... 省略部分代码 ...
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
beanFactory.getBean(beanName));
// ... 省略部分代码 ...
return beanInstance;
// ... 省略部分代码 ...
可以看到,在 resolveBeanReference
方法中,会通过 beanFactory
获取已经初始化好的 bean
对象,并将这个已经初始化好的 bean
对象返回,并不会再进行第二次初始化的操作。
四、总结
做一个简单的思维导图。
参考连接:【冰河的星球】https://articles.zsxq.com/id_88k0ww2tsr6n.html