[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
本文来自博客园,作者:knqiufan,转载请注明原文链接:https://www.cnblogs.com/knqiufan/p/17426900.html

浙公网安备 33010602011771号