[Spring 6.0源码解析] @Configuration注解源码解析

发布时间 2023-05-24 02:25:22作者: knqiufan

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 源码分析

ConfigurationClassPostProcessorSpring中最重要的后置处理器。@Configuration注解解析涉及到了 ConfigurationClassPostProcessor 类的注册流程。

从启动代码中可以看到,使用了 AnnotationConfigApplicationContext 类的构造方法传入了配置类 ConfigurationAnnotationConfig,来创建了 IOC 容器,那么我们就以此为入口进行分析。

使用的 AnnotationConfigApplicationContext 类构造方法如下:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigurationAnnotationConfig.class);
  1. 进入该构造方法:
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    register(componentClasses);
    refresh();
}

可以看到,在上述构造方法中,先调用了 AnnotationConfigApplicationContext 类的无参构造方法 this()

  1. 分析这个 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 类的成员变量 readerreader主要是为了解析带有注解的 Bean 的 BeanDefinition,并将其注册到 Bean 工厂中。
  • 实例化 ClassPathBeanDefinitionScanner 类的成员变量 scannerscanner会扫描指定包下的类,并将符合过滤条件的类注册到IOC容器内。

注:StartupStep 接口主要作用是为了跟踪应用程序的启动顺序。

分析实例化 reader 这个成员变量的代码,也就是如下代码片段:

this.reader = new AnnotatedBeanDefinitionReader(this);

  1. 调用了 AnnotatedBeanDefinitionReader 的构造方法:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    this(registry, getOrCreateEnvironment(registry));
}
  1. 其中又调用了 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 类继承了 GenericApplicationContextGenericApplicationContext 类 又实现了BeanDefinitionRegistry 接口。

  1. 分析 AnnotationConfigUtils 调用的 registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)方法,源码如下:
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
    registerAnnotationConfigProcessors(registry, null);
}
  1. 继续分析调用的 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 方法,从方法名就可以看出,注册后置处理器。进入这个方法。

  1. 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 实例。

  1. 进入注册方法 registerBeanDefinition,源码如下:
public interface BeanDefinitionRegistry extends AliasRegistry { 
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
    // .....
}

是调用了BeanDefinitionRegistry接口的registerBeanDefinition方法。

在之前的 UML 图中可以知道,AnnotationConfigApplicationContext 类继承了 GenericApplicationContextGenericApplicationContext 类 又实现了BeanDefinitionRegistry 接口,所以跳转到GenericApplicationContext类的实现。

  1. 源码如下:
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {

    this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}

可以看到,实际上是调用了 DefaultListableBeanFactory 类的 registerBeanDefinition 方法。this.beanFactoryDefaultListableBeanFactory 类的实例。

  1. 分析 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);
            // ... 省略其他代码 ...
        }

        // ... 省略其他代码 ...

    }

通过这段代码可以看到,其实向 SpringIOC容器中注册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 的注册。

  1. 进入 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 进行注册。

  1. 分析 reader 对象的 register 方法。

注:reader 对象在这里就是 AnnotatedBeanDefinitionReader 的实例化对象

public void register(Class<?>... componentClasses) {
    for (Class<?> componentClass : componentClasses) {
        registerBean(componentClass);
    }
}

register 方法中循环遍历传入的可变参数,每次循环都会调用 registerBean 方法。

  1. 分析 registerBean 方法
public void registerBean(Class<?> beanClass) {
    doRegisterBean(beanClass, null, null, null, null);
}

registerBean 中又调用了 doRegisterBean 方法。

  1. 分析 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() 方法。

AnnotationConfigUtilsapplyScopedProxyMode方法主要是为了解析 Bean 中的@Scope注解,应用 @Scope注解中的 ProxyMode属性。这里不做重点讲解。

  1. 主要解析 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);
        }
    }

}

可以看到,这边也使用了 registryregisterBeanDefinition 方法向 IOC 容器中注册了 Bean。从上面的跟踪代码可知,调用 registry.registerBeanDefinition() 方法注册的 Bean 其实就是ConfigurationAnnotationConfig配置类。

而这部分的注册源码逻辑与之前注册 ConfigurationClassPostProcessor 类的代码相同,同样是调用了 DefaultListableBeanFactory 类的 registerBeanDefinition 方法,不再重复分析。

至此我们可以看到,这部分就是对 ConfigurationAnnotationConfig 配置类的 Bean 进行了注册。

三、实例化流程源码分析

上面分析了注册 ConfigurationClassPostProcessor 后置处理器的源码与注册 ConfigurationAnnotationConfig 配置类的源码,接下来继续分析,Spring IOC 容器在刷星时,会实例化 @Configuration 注解标注的类。

  1. 继续从这个构造函数开始:
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    register(componentClasses);
    refresh();
}

可以看到,是调用了 refresh() 这个方法来刷新 Spring IOC 容器。

  1. 进入 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 的执行过程。

  1. 进入 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 静态方法。

  1. 进入 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 方法。

  1. 进入 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 方法。

  1. 解析 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 方法。

  1. 解析 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 生成代理类。

  1. 解析 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 对象。

  1. 先看 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 对象。

  1. 接着来看 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的方法,创建的代理类目标类的子类,所以这里创建出来的代理类是目标类的子类。

  1. 关注下 CALLBACKS 这个参数。
static final Callback[] CALLBACKS = new Callback[] {
    new BeanMethodInterceptor(),
    new BeanFactoryAwareMethodInterceptor(),
    NoOp.INSTANCE
};

可以看到 CALLBACKS 这个参数其实是个 Callback 类型的数组,数组中的每个元素都是 Callback 类型。同时 BeanMethodInterceptorBeanFactoryAwareMethodInterceptor 类也是拦截器类型。

BeanMethodInterceptor 类实现了 MethodInterceptor 接口和 ConditionalCallback 接口,主要作用是对标注了 @Bean 的注解方法进行拦截,执行 intercept 方法来生成 Bean 的实例对象。

  1. 浅看一下 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