Spring IoC容器不仅管理对象(bean)的实例化,而且还管理协作者(或依赖项)的连接。 如果要将(例如)HTTP请求范围的Bean注入(例如)另一个作用域更长的Bean,则可以选择注入AOP代理来代替已定义范围的Bean。 也就是说,您需要注入一个代理对象,该对象公开与范围对象相同的公共接口,但也可以从相关范围(例如HTTP请求)中检索实际目标对象,并将方法调用委托给实际对象。

您还可以在范围为单例的bean之间使用<aop:scoped-proxy />,然后引用通过经过可序列化的中间代理,从而能够在反序列化时重新获得目标单例bean。

当针对范围原型的bean声明<aop:scoped-proxy />时,共享代理上的每个方法调用都会导致创建新的目标实例,然后将该调用转发到该目标实例

同样,作用域代理不是以生命周期安全的方式从较短的作用域访问bean的唯一方法。 您也可以将注入点(即构造器或setter参数或自动装配的字段)声明为ObjectFactory ,从而允许getObject()调用在需要时按需检索当前实例。 实例或将其单独存储。

作为扩展的变体,您可以声明ObjectProvider ,它提供了几个附加的访问变体,包括getIfAvailable和getIfUnique。

JSR-330的这种变体称为Provider,并与Provider 声明和每次检索尝试的相应get()调用一起使用。 有关JSR-330总体的更多详细信息,请参见此处。

以下示例中的配置仅一行,但是了解其背后的“原因”和“方式”很重要:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!-- an HTTP Session-scoped bean exposed as a proxy --><bean id="userPreferences" class="com.something.UserPreferences" scope="session"><!-- instructs the container to proxy the surrounding bean --><aop:scoped-proxy/> </bean><!-- a singleton-scoped bean injected with a proxy to the above bean --><bean id="userService" class="com.something.SimpleUserService"><!-- a reference to the proxied userPreferences bean --><property name="userPreferences" ref="userPreferences"/></bean>
</beans>

要创建这样的代理,需要将一个子aop:scoped-proxy元素插入到有作用域的bean定义中(参见选择要创建的代理类型和基于XML模式的配置)。</aop:scoped-proxy>为什么在请求、会话和自定义范围级别定义作用域的bean需要aop:作用域代理元素?</aop:作用域代理>考虑一下下面的单例bean定义,并将它与您需要为前面提到的作用域定义的内容进行对比(请注意,下面的userPreferences bean定义是不完整的):

<bean id="userPreferences" class="com.something.UserPreferences" scope="session"/><bean id="userManager" class="com.something.UserManager"><property name="userPreferences" ref="userPreferences"/>
</bean>

在前面的示例中,单例bean(userManager)注入了对HTTP会话作用域bean(userPreferences)的引用。 这里的重点是userManager bean是单例的:每个容器仅实例化一次,并且其依赖项(在这种情况下,仅一个,userPreferences bean)也仅注入一次。 这意味着userManager bean仅在完全相同的userPreferences对象(即最初与之注入对象)上操作。

将寿命较短的作用域bean注入寿命较长的作用域bean时,这不是您想要的行为(例如,将HTTP“会话”作用域的协作bean作为依赖项注入到singleton bean中)。 相反,您只需要一个userManager对象,并且在HTTPSession的生命周期中,您需要一个特定于HTTPSessionuserPreferences对象。 因此,容器创建了一个对象,该对象公开了与UserPreferences类完全相同的公共接口(理想情况下是一个UserPreferences实例的对象),该对象可以从范围界定机制(HTTP请求, “会话”,依此类推)。 容器将这个代理对象注入到“ userManager” bean中,这并没有意识到“ UserPreferences”引用是一个代理。 在这个例子中,当一个UserManager实例在依赖项注入的UserPreferences对象上调用一个方法时,它实际上是在代理上调用一个方法。 然后,代理从(在这种情况下)HTTPSession获取实际的“ UserPreferences”对象,并将方法调用委托给检索到的实际“ UserPreferences”对象。

<bean id="userPreferences" class="com.something.UserPreferences" scope="session"><aop:scoped-proxy/>
</bean><bean id="userManager" class="com.something.UserManager"><property name="userPreferences" ref="userPreferences"/>
</bean>

默认情况下,当Spring容器为使用<aop:scoped-proxy />元素标记的bean创建代理时,将创建基于CGLIB的类代理。

CGLIB代理仅拦截公共方法调用! 不要在此类代理上调用非公共方法。 它们没有被委派给实际的作用域目标对象。

另外,您可以通过为<aop:scoped-proxy />元素的proxy-target-class属性值指定false,来配置Spring容器为此类作用域的bean创建基于标准JDK接口的代理。 使用基于JDK接口的代理意味着您不需要应用程序类路径中的其他库即可影响此类代理。 但是,这也意味着作用域Bean的类必须实现至少一个接口,并且作用域Bean注入到其中的所有协作者必须通过其接口之一引用该Bean。 以下示例显示基于接口的代理:

<!-- DefaultUserPreferences implements the UserPreferences interface -->
<bean id="userPreferences" class="com.stuff.DefaultUserPreferences" scope="session"><aop:scoped-proxy proxy-target-class="false"/>
</bean><bean id="userManager" class="com.stuff.UserManager"><property name="userPreferences" ref="userPreferences"/>
</bean>

英文文档地址:

https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/core.html#beans-factory-scopes-other-injection

中英文对照
https://www.qqkj.vip/archives/scoped-beans-as-dependencies

spring如何注入作用域不同的bean相关推荐

  1. Spring依赖注入的方式、类型、Bean的作用域、自动注入、在Spring配置文件中引入属性文件...

    1.Spring依赖注入的方式 通过set方法完成依赖注入 通过构造方法完成依赖注入 2.依赖注入的类型 基本数据类型和字符串 使用value属性 如果是指向另一个对象的引入 使用ref属性 User ...

  2. spring bean作用域_Srping中Bean的三种装配方式:大魏Java记10

    一.Bean的作用域 Spring在初始化一个Bean实例时,可以同时为其指定特定的作用域.作用域将会对Bean的生命周期和创建方式产生影响. Bean的作用域类型: Singleton作用域是Spr ...

  3. Spring概念、类注解和Bean作用域

    1.Spring 是什么? 我们通常所说的 Spring 指的是 Spring Framework(Spring 框架),它是⼀个开源框架,有着活跃而庞⼤的社区,这就是它之所以能长久不衰的原因.Spr ...

  4. Spring框架XML配置文件使用外部Bean属性注入

    Spring框架XML配置文件使用外部Bean属性注入 (1)创建两个类service类和dao类 (2)在service中调用dao里面的方法 (3)使用Spring框架进行调用 (4)创建测试类 ...

  5. spring学习---IOC--基于xml--bean管理--spring创建对象--spring注入属性--其他属性注入--外部bean--内部bean

    基于xml配置以下 bean管理 实现两种操作 a).spring创建对象 1.基于XML方式创建对象: <!-- 配置User对象的创建--><bean id = "us ...

  6. Spring依赖注入Bean为空,注入失效场景

    场景介绍 使用spring往一个bean(BeanB)注入另一个bean(BeanA),发现BeanA为null,注入失败了. 代码展示 /*** @author huangd* @date 2021 ...

  7. 【Spring源码分析系列】bean的加载

    前言 以 BeanFactory bf  = new XmlBeanFactory(new ClassPathResource("beans.xml"));为例查看bean的加载过 ...

  8. java接口注入对象的意义_Java Web系列:Spring依赖注入基础

    一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是 ...

  9. Spring Singleton,请求,会话Bean和线程安全

    由众多有用框架组成的Spring框架生态系统已成为许多Java EE应用程序的基础. 但是在所有Spring产品的核心中,我们仍然拥有Spring DI / IOC框架,该框架将Spring推向了新的 ...

最新文章

  1. WINCE6.0更换桌面壁纸和图标
  2. 数据驱动决策的10种思维方式
  3. 人事薪资管理系统V1.00功能简介(适用于工厂)c#.net+SQL Server2000
  4. LeetCode 325. 和等于 k 的最长子数组长度(哈希表记录第一次出现的状态)
  5. 使用广播信道的以太网
  6. win10系统更新在哪_五步教你win10永久关闭系统自动更新
  7. java 无法import_ImportError:无法导入名称X
  8. [转]nodejs Error: request entity too large解决方案
  9. 计算机办公自动化知识试题及答案,2015年计算机办公自动化考试试题及答案
  10. 硬笔行书字帖3500常用字_2018年【成年人实用硬笔行书】一对一直播培训简介
  11. Unity给力插件之ShaderForge
  12. 10分钟搞定图形图像识别
  13. 标题 多媒体计算机的标准是什么,多媒体技术习题答案
  14. 中山大学计算机学院师资,中山大学计算机学院导师教师师资介绍简介-农革
  15. 10G整数中寻找中位数
  16. 数独问题每行每列每3X3
  17. Istio,下一个Kubernetes?
  18. Vue中引入字体并解决字体文件过大问题
  19. mybatis报错:java.sql.SQLException: 无效的列类型: 1111
  20. 时间序列预测必读的20篇论文!

热门文章

  1. 1. Java并发编程-Java内存模型
  2. SparkSQL内置函数
  3. 前端H5—jQuery精通-张晓飞-专题视频课程
  4. matlab无向图 有向图画法
  5. [编译原理]吉林大学编译原理csf课件下载(1-64) 主讲:康辉 (附破解补丁)
  6. 设计模式-简单总结(不涉及代码,有需要戳)
  7. 51单片机用STC—ISP烧录程序是一直显示“正在检测目标单片机···”冷启动板子没有反应
  8. CVE-2017-8464远程命令执行漏洞(震网漏洞)复现
  9. 给iframe添加loading状态
  10. AI就业前景越来越严峻了,AI 开发者能怎样提升个人竞争优势?