首页 > 其他分享 >singlleton 的 bean 中注入 prototype 的bean

singlleton 的 bean 中注入 prototype 的bean

时间:2024-09-28 21:35:52浏览次数:9  
标签:singlleton Bean bean 实例 注入 prototype public prototypeBeanA

在 Spring 中,prototype Bean 注入 prototype Beansingleton Bean 注入 prototype Bean 是两个典型的场景,尤其在多线程、状态管理等复杂系统中,会有不同的行为和注意事项。

1. prototype Bean 中注入 prototype Bean

当一个 prototype Bean 注入另一个 prototype Bean 时,每次获取外部的 prototype Bean 实例时,Spring 会为该 Bean 创建一个新的实例。这种情况较为简单,因为 prototype 作用域的 Beans 都是动态生成的新实例。

特点:

  • 每个 prototype Bean 都是独立的,每次请求都会创建一个新对象。
  • Spring 管理 Bean 的创建和初始化,但不会管理 prototype Bean 的销毁。

示例:

@Component
@Scope("prototype")
public class PrototypeBeanA {
    // Prototype Bean A 的逻辑
}

@Component
@Scope("prototype")
public class PrototypeBeanB {
    
    @Autowired
    private PrototypeBeanA prototypeBeanA;

    public void doSomething() {
        // 每次使用的 prototypeBeanA 都是新的实例
        System.out.println(prototypeBeanA);
    }
}

结果:

  • 每次 PrototypeBeanB 被创建时,PrototypeBeanA 也会是一个全新的实例。
  • 因为 PrototypeBeanBprototype 作用域的,所以每次创建 PrototypeBeanB 时,PrototypeBeanA 都会重新注入一个新的实例。

2. singleton Bean 中注入 prototype Bean

这是一个常见的复杂场景,因为 singleton Bean 是单例,而 prototype Bean 是多例。一旦 singleton Bean 被创建,所有的依赖都将固定下来。如果在 singleton Bean 中直接注入 prototype Bean,那么这个 prototype Bean 实际上只会被创建一次,并且在整个应用程序的生命周期中都只会有这个唯一的实例,这显然与 prototype Bean 的设计初衷不符。

特点:

  • 问题:当 singleton Bean 注入 prototype Bean 时,注入的 prototype Bean 只会初始化一次,之后不会再创建新的实例。每次使用的都是同一个 prototype 实例。
  • 解决方法:为了确保 singleton Bean 每次使用 prototype Bean 时都能获取到新的 prototype 实例,必须使用一些特殊的技术,如 @Lookup 方法注入ObjectFactoryProvider

示例 1:直接注入 prototype Bean(错误方式)

@Component
public class SingletonBean {
    
    @Autowired
    private PrototypeBeanA prototypeBeanA;

    public void doSomething() {
        // 每次调用时都会使用同一个 prototypeBeanA 实例
        System.out.println(prototypeBeanA);
    }
}

在这个例子中,prototypeBeanA 只会被创建一次,因此每次调用 doSomething() 方法时,prototypeBeanA 都是同一个实例,这与 prototype 的预期不一致。

示例 2:使用 @Lookup 方法(正确方式)

@Lookup 注解告诉 Spring 每次调用这个方法时,都需要返回一个新的 prototype 实例。

@Component
public class SingletonBean {
    
    @Lookup
    public PrototypeBeanA getPrototypeBeanA() {
        // Spring 将返回新的 PrototypeBeanA 实例
        return null; // 这个返回值会被 Spring 动态代理替换
    }

    public void doSomething() {
        PrototypeBeanA prototypeBeanA = getPrototypeBeanA();
        System.out.println(prototypeBeanA); // 每次获取的都是新的实例
    }
}

示例 3:使用 ObjectFactory 注入

ObjectFactory 是 Spring 提供的一个工厂接口,用来在每次调用时动态获取 prototype Bean。

@Component
public class SingletonBean {
    
    @Autowired
    private ObjectFactory<PrototypeBeanA> prototypeBeanFactory;

    public void doSomething() {
        PrototypeBeanA prototypeBeanA = prototypeBeanFactory.getObject();
        System.out.println(prototypeBeanA); // 每次获取的都是新的实例
    }
}

示例 4:使用 Provider 注入

javax.inject.Provider 也提供类似的动态获取 prototype Bean 的功能。

@Component
public class SingletonBean {
    
    @Autowired
    private Provider<PrototypeBeanA> prototypeBeanProvider;

    public void doSomething() {
        PrototypeBeanA prototypeBeanA = prototypeBeanProvider.get();
        System.out.println(prototypeBeanA); // 每次获取的都是新的实例
    }
}

3. 总结对比

场景 prototype Bean 注入 prototype Bean singleton Bean 注入 prototype Bean
默认行为 每次注入时都会创建新的 prototype 实例 注入的 prototype Bean 只会创建一次(单例生命周期内只创建一次)
常见问题 行为符合预期,每次使用新的 prototype 实例 singleton Bean 会持有同一个 prototype 实例,违背 prototype 设计初衷
解决方案 默认情况下即可实现正确行为 使用 @Lookup 方法、ObjectFactoryProvider 实现动态获取新的 prototype 实例

4. 结论

  • prototype Bean 注入 prototype Bean 时,Spring 的默认行为是符合预期的,每次使用时都会创建新的实例。
  • singleton Bean 需要注入 prototype Bean 时,必须采用 @LookupObjectFactoryProvider 方式来确保每次都能获取新的 prototype 实例,否则默认情况下只会创建一个实例。

标签:singlleton,Bean,bean,实例,注入,prototype,public,prototypeBeanA
From: https://www.cnblogs.com/gongchengship/p/18438452

相关文章

  • Java反射机制的原理、核心类、实际应用、优缺点、具体工具类BeanUtils。
    小二,来客人了客官有请:文章目录1.什么是Java反射机制?2.反射的核心类有哪些?3.使用反射前的准备......
  • BeanFactery实现IOC,DI思想
    一.三种思想(Ioc,DI,AOP)Iocinversionofcontrol,控制反转,强调的是原来在程序中创建bean的权利反转给第三方。DIdepencyinjection,依赖注入,强调的是bean之间的关系,由第三方负责设置。AOPaspectorientedprogramming,面向切面编程,功能的横向抽取,主要的实现方式就是Proxy。......
  • jmeter Beanshell语法
    获取变量vars.get("variable_name");设置变量vars.put("variable_name");获取全局变量props.get("variable_name");设置全局变量props.put("variable_name");获取响应头prev.getResponseHeaders();获取响应码prev.getResponseCode();获取响应结果prev.getResponseDataAsSt......
  • Java BeanUtils使用介绍
    ‌JavaBeanUtils是一个广泛使用的Java工具类,提供了一系列方法来简化JavaBean对象之间的属性复制和操作。‌使用JavaBeanUtils可以方便地实现对象之间的属性复制、属性设置和获取、类型转换等功能。以下是使用JavaBeanUtils的基本步骤和注意事项:1.添加依赖‌:首先,你需要在项目......
  • java浅拷贝BeanUtils.copyProperties引发的RPC异常
    背景近期参与了一个攻坚项目,前期因为其他流程原因,测试时间已经耽搁了好几天了,本以为已经解决了卡点,后续流程应该顺顺利利的,没想到人在地铁上,bug从咚咚来~没有任何修改的服务接口,抛出异常:java.lang.ClassCastException:java.util.HashMapcannotbecasttocn.xxx.xxx.xxx.xx......
  • Invalid bean definition with name ‘myBatisPlusApplication‘ defined in class pa
    目录问题出现背景问题分析问题解决一、背景        黑马课程的SSM框架里面的MyBatisPlus部分的学习,学习的是selecPage方法的测试时候出现的,因为要配分页的拦截器,所有定义了一个config的类,同时配了@Configuration(@Component好像也可正常使用),然后去到测试时候就......
  • SpringUtil获取bean
    packagecom.joysuccess.dcim.alarm.utils;importorg.springframework.beans.BeansException;importorg.springframework.context.ApplicationContext;importorg.springframework.context.ApplicationContextAware;importorg.springframework.stereotype.Component;......
  • Spring Boot利用dag加速Spring beans初始化
    1.什么是Dag?有向无环图(DirectedAcyclicGraph),简称DAG,是一种有向图,其中没有从节点出发经过若干条边后再回到该节点的路径。换句话说,DAG中不存在环路。这种数据结构常用于表示并解决具有依赖关系的问题。DAG的特性首先,DAG中的节点可以有入度和出度。节点的入度是指指向该......
  • 二,MyBatis -Plus 关于映射 Java Bean 对象的注意事项和细节(详细说明)
    二,MyBatis-Plus关于映射JavaBean对象的注意事项和细节(详细说明)文章目录二,MyBatis-Plus关于映射JavaBean对象的注意事项和细节(详细说明)1.映射2.表的映射3.字段映射4.字段失效5.视图属性6.总结:7.最后:1.映射这里的映射:是指将从数据库查询到的信......
  • niubility!即使JavaBean没有默认无参构造器,Fastjson也可以反序列化。- - - - 阿里Fastj
    niubility!即使JavaBean没有默认无参构造器,fastjson也可以反序列化。看下面示例代码,User这个JavaBean不包含默认无参构造器。执行这段代码不仅不会像Jackson那样抛出“没有无参构造器”的异常,还能正常反序列化。@TestpublicvoidtestFastjsonCoDec(){StringjsonString=......