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. 独家 | 深度学习基础——激活函数以及什么时候使用它们?(附代码)
  2. 从手机App通过WebSocket向浏览器推送数据
  3. 小程序 仿麦当劳_手机上的麦当劳和星巴克:为什么现在首先使用移动应用程序...
  4. 2.支付平台架构:业务、规划、设计与实现 --- 收银台系统
  5. getmethodid( android/widget/toast ),Android功能实现-Go语言中文社区
  6. 股票开户天载钢铁等板块跌幅居前
  7. rm -rf 真是删库跑路的一把好手
  8. java对接支付宝三方登录
  9. 中国软件业的机会——抓住机遇、挑战未来
  10. 关于跳跃连接 卷积网络
  11. 外文翻译原文附在后面_外文翻译原文及配套译文
  12. Ubuntu 中文 Wiki
  13. (网页)Http状态码大全(200、404、500等)(转CSDN)
  14. 用matlab编程节点电压法求电路,MATLAB在电路中的应用
  15. iOS-NSUserDefaults详解
  16. 广工计算机网络课程设计FTP服务器,计算机网络-课程设计报告(FTP客户端的设计和实现).doc...
  17. 如何节约手游制作成本?揭秘CocoStudio编辑器强悍功能
  18. WPF 设置图片的分辨率DPI
  19. 3-4 3.4编程计算一元二次方程的根
  20. 【PHP】一文详解如何连接Mysql数据库(附源码)

热门文章

  1. php求解鸡鸭同笼,鸡兔同笼的9种解法
  2. python程序设计第二章序列类型 题库及选解
  3. html5 websocket 游戏,基于Websocket的H5在线游戏对战平台
  4. MySQL中文乱码问题处理详解
  5. Django项目连接MongoDB的三种方法
  6. cento网络故障:Job for network.service failed because the control process exited with error code. See sy
  7. Prometheus部分监控项
  8. 程序员迎娶白富美的唯一出路是什么? 认真用心写代码
  9. 环形缓冲区ringbuffer c++类模版实现
  10. SpringBoot是如何动起来的