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

本文涉及的产品
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 【6月更文挑战第8天】学习 Spring 框架内不原理的意义就是,当遇到问题时,分析出原因,就可以从多个切入点,利用 Spring 的特性,来解决问题。

根据 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 的特性,来解决问题。

目录
相关文章
|
23天前
|
XML Java 数据格式
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
24 1
|
23天前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
26 0
|
23天前
|
Java Spring 容器
spring如何进行依赖注入,通过set方法把Dao注入到serves
spring如何进行依赖注入,通过set方法把Dao注入到serves
|
24天前
|
Java Spring 容器
解读spring5源码中实例化单例bean的调用链
解读spring5源码中实例化单例bean的调用链
|
27天前
|
运维 Java 关系型数据库
Spring运维之boot项目bean属性的绑定读取与校验
Spring运维之boot项目bean属性的绑定读取与校验
28 2
|
16天前
|
Java 微服务 Spring
微服务04---服务远程调用,根据订单id查询订单功能,根据id查询订单的同时,把订单所属的用户信息一起返回,Spring提供了一个工具RestTemplate,Bean写在对象前面,以后可以在任何地
微服务04---服务远程调用,根据订单id查询订单功能,根据id查询订单的同时,把订单所属的用户信息一起返回,Spring提供了一个工具RestTemplate,Bean写在对象前面,以后可以在任何地
|
23天前
|
Java Spring
Spring注解内容----用来替代Bean
Spring注解内容----用来替代Bean
|
23天前
|
Java Linux 程序员
技术笔记:Spring生态研习【五】:Springboot中bean的条件注入
技术笔记:Spring生态研习【五】:Springboot中bean的条件注入
|
24天前
|
Java Spring
聊聊Spring中两种创建Bean的方式:BeanDefinition.setInstanceSupplier() 和 FactoryBean
聊聊Spring中两种创建Bean的方式:BeanDefinition.setInstanceSupplier() 和 FactoryBean
|
24天前
|
Java 开发者 Spring
Spring的Bean的生命周期各个阶段扩展方法
Spring的Bean的生命周期各个阶段扩展方法