解决 Spring 中 Prototype Bean 注入后被固定的问题

这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战

根据 Spring 的文档,Spring 中的 Bean 的 Scope 共有 5 种:singleton、prototype、request、session、application、websocket。其中,singleton 是默认值,也是最常用的,除此之外最常用的就是 prototype,其余都很少会用到。

当一个 Singleton 的 Bean,使用 @Autowired 注入一个属性的时候,这个属性的值就被固定了,这里会存在一个问题,就是如果这个属性是一个 Prototype 的 Bean,那么,它也会被固定了,也就是不会发生变化了。这显然不是我们期望的情况。

因此,当在一个 Singleton 的 Bean 中注入一个 Prototype 的 Bean 作为属性的时候,我们不能直接将其注入,而是需要采用一些其他的方式。有以下几种方式可以解决这个问题:

第一种,使用 @Lookup 注解。

@Component
public class SingletonBean {
    
    public void some() {
        getPrototypeBean().doSomething();
    }
    
    @Lookup
    public PrototypeBean getPrototypeBean() {
        return null;
    }
    
}
复制代码

被 @Lookup 注解标记之后,当这个方法被调用的时候,实际会调用CglibSubclassingInstantiationStrategy.LookupOverrideMethodInterceptor#inspect 方法,从 BeanFactory 种查找 PrototypeBean。也正是因为这个方法并不会真的被调用,因此,方法体种可以写任何代码,这些代码都不会被执行。最简单的就是直接返回空。

第二种方法,就是不注入这个 Prototype 的 Bean,而是注入 ApplicationContext,每当需要使用这个 Bean 的时候,就从 ApplicationContext 种查找这个 Bean,因为这个 Bean 是 Prototype 的,因此,每次从 ApplicationContext 中获取的时候,都会获取到一个新的 Bean。这样就解决了文章开头我们描述的问题:

@Component
public class SingletonBean {

    @Autowired private ApplicationContext applicationContext;
    
    public void some() {
        getPrototypeBean().doSomething();
    }
    
    public PrototypeBean getPrototypeBean() {
        return applicationContext.getBean(PrototypeBean.class);
    }
    
}
复制代码

以上就是解决 Prototype Bean 被注入到 Singleton Bean 之后,被固定的问题的两种办法。

这个问题在日常的开发中,不是一个常见的问题,也是一个容易被忽略也不容易排查的问题。同时,这个问题,也没有一个标准的解决方案,我们可以根据了解到的 Spring 的原理知识,找到不止一种解决方案。这也是我们学习 Spring 框架内不原理的意义,当遇到问题时,分析出原因,就可以从多个切入点,利用 Spring 的特性,来解决问题。

Supongo que te gusta

Origin juejin.im/post/7066434867352829988
Recomendado
Clasificación