@Bean 注解的方法调用多次会创建多个bean 实例吗

本文探讨了在Spring中,@Bean注解的方法被多次调用是否会创建多个实例的问题。通过分析发现,Spring利用CGLIB代理确保了同一配置类内对@Bean方法的调用只会创建一个bean实例。文章详细解释了这一机制,涉及ConfigurationClassEnhancer、BeanMethodInterceptor等核心组件的工作原理。
摘要由CSDN通过智能技术生成

1.缘起

在看一段基于 spring security 的鉴权代码的时候,我发现一个有趣的 Bean 声明和方法调用。在一个 @Configuration 注解的配置类中用 @Bean 注解了一个方法 tokenStore,声明了 Spring bean: tokenStore。在 Spring 中,把 @Bean 注解的方法称为工厂方法,即用于创建 Spring bean 的方法。在同一个配置类另一个方法 configure 中调用了这个工厂方法 tokenStore 来获取 TokenStore 实例。

那么这会导致系统中存在多个 TokenStore 实例吗?如果是两个实例,则一个应该是 Spring bean 实例,一个是 configure 方法中通过 tokenStroe() 方法创建的实例。代码如下:

@Configuration
public class AuthorizationConfig {

    @Bean
    public TokenStore tokenStore() {
        RedisTokenStore redis = new RedisTokenStore(connectionFactory);
        return redis;
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        /*使用oauth2的密码模式时需要配置authenticationManager*/
        endpoints.authenticationManager(authenticationManager);
        //直接调用工厂方法获取 TokenStore 实例
        endpoints.tokenStore(tokenStore())
        ...
    }
    ...
}

答案是否定的,在系统中只有一个实例,这个实例就是 spring bean。这是怎么做到的呢?继续阅读之前,可以闭上眼睛思考一下。

2.原理

通过调式代码,我们可以发现这个配置类已经被 CGLIB 代理了,这个配置类的实例类名变成了 AuthorizationConfig$$EnhancerBySpringCGLIB,如图: 

断点堆栈如图: 

 这个堆栈图从最底下向上看,配置类的 configure 方法调用本类工厂方法 tokenStore,变成了调用AuthorizationConfig$$EnhancerBySpringCGLIB 的tokenStore了,而这个调用被 ConfigurationClassEnhancer$$BeanMethodInterceptor 拦截器拦截,接着堆栈出现了我们熟悉的 Spring getBean 的调用堆栈(当 bean 不存在的时候,就会触发创建 bean)。

由此可见spring 容器通过 CGLIB 代理了配置类,调用配置类 @Bean 注解的工厂方法时,这个方法会被拦截。拦截器会通过 Spring 容器的机制去获取这个工厂方法上声明的 bean,如果这个bean 实例还不存在,Spring 容器会创建 bean 实例,而这个 bean 是通过配置类的 tokenStore 方法创建的,所以最终找到通过代理类调用到了配置类的 tokenStore 方法创建了 bean 实例。

3.机制探究

Spring 为 @Configuration 专门设计了一个 BeanFactoryPostProcessor 实现类ConfigurationClassPostProcessorÿ

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值