Spring 源码分析:@Bean 原理


#Spring


Spring 版本: 5.2.2.RELEASE

本文涉及到 cglib 的知识,可以在 Java:使用 cglib 实现动态代理 了解。

@Bean 必须在 @Configuration 注解的类中才能生效。

所以 @Bean 有3个阶段:

  1. 增强 @Configuration 注解的类
  2. Spring 扫描得到所有 @Bean 方法
  3. 生成 Spring bean 实例

原理

阶段1:增强 @Configuration 注解的类

大致执行时序:

AbstractApplicationContext -> AbstractApplicationContext: refresh()
AbstractApplicationContext -> AbstractApplicationContext: invokeBeanFactoryPostProcessors()
AbstractApplicationContext -> PostProcessorRegistrationDelegate: invokeBeanFactoryPostProcessors
PostProcessorRegistrationDelegate -> ConfigurationClassPostProcessor: enhanceConfigurationClasses
ConfigurationClassPostProcessor -> ConfigurationClassEnhancer: enhance

ConfigurationClassEnhancer # enhance 执行完后,我们会得到 @Configuration 注解的类的一个增强类。这个增强类是基于 cglib 实现的原始类的子类。

ConfigurationClassEnhancer 中的重点代码:


// 这个callback,会在生成 spring bean 时被调用
private static final Callback[] CALLBACKS = new Callback[] {
        new BeanMethodInterceptor(),
        new BeanFactoryAwareMethodInterceptor(),
        NoOp.INSTANCE
};

// 对类进行增强(即用cglib对类代理一层)
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
    if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
        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;
}

// 下面是 cglib 的增强代码
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));
    enhancer.setCallbackFilter(CALLBACK_FILTER);
    enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
    return enhancer;
}
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;
}

因为增强类是动态生成的,肯定也会有一定的命名策略。对于增强类,是在基础类类名的基础上追加$BySpringCGLIB。具体可查看 Spring 中的 AbstractClassGenerator 中的 generateClassName 方法、 SpringNamingPolicy 类。

阶段2:Spring 扫描得到所有 @Bean 方法

Spring 会通过扫描拿到所有 Bean 的元数据。但这一步,不会生成实例。

阶段3:生成 Spring bean 实例

在 ConfigurationClassEnhancer 中生成cglib 增强类时使用了3个 interceptor: BeanMethodInterceptor 、BeanFactoryAwareMethodInterceptor、NoOp.INSTANCE 。

Spring 是通过执行 @Bean 注解的方法生成 bean,而执行方法时,会经过 cglib interceptor 。interceptor 内部则是基于 BeanFactory 去生成bean。

这种方式有两个特点:

  1. 调用 @Bean 注解的方法时,得到的是单例。
  2. @Configuration 注解的类内部,@Bean 方法直接互相调用,得到的也是单例,因为这里用的是方法级的 interceptor (Method Interceptor)。


( 本文完 )