Spring framework不同Scope的Bean注入时使用代理类的理解

教程:Bean作用域 Bean作用域 4 singleton作用域 4 prototype作用域 5 具有原型Bean依赖的单例Bean 7 Request, Session, Application, 和 WebSocket 作用域 7 初始网络配置 7 request作用域 8 session作用域 8 application作用域 9 websocket作用域 9 作用域 Bean 作为依赖项 9 选择要创建的代理类型 11 直接注入Request/Session引用 11 自定义作用域 11 创建自定义作用域 11 使用 阅读详情

最近没事在看Spring framework的参考文档,对部分有疑问的地方写些简单的demo测试一下。

以下是一个例子测试使用@Bean注解配置不同Scope的Bean注入时的效果是否与XML配置时一致。

1.首先写一个Bean的配置类,在singleton的MyService中注入prototype的MyMode类。这里使用接口为了能自由选择JDK动态代理或CGLIB


Mode接口

package com.bean;

public interface IMode {
    public void print();
}


Mode实现

package com.bean;

import java.util.concurrent.atomic.AtomicInteger;

public class MyMode implements IMode {

	private static AtomicInteger i = new AtomicInteger(0);

	private int value;

	public MyMode() {
		System.out.println("MyMode constructor call");
		this.value = i.incrementAndGet();
	}

	public void print() {
		System.out.println("MyMode print called");
		System.out.println(value);
	}

}



Service接口

package com.bean;

public interface IService {

	public IMode getMode();
}

Service实现

package com.bean;

public class MyService implements IService{

	private IMode mode;
	
	public MyService() {

	}

	public MyService(IMode mode) {
		this.mode = mode;
	}
	
	public IMode getMode() {
		return mode;
	}

	public String toString() {
		if(mode==null){
			return "none mode in service";
		}
		return  "bingo";
	}
}


Bean配置类

package com;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;

import com.bean.IMode;
import com.bean.MyMode;
import com.bean.MyService;


@Configuration("test")
public class TestBeanConfigration {

	@Bean
	public IService myService(){
		return new MyService(myMode());
	}

	@Bean
	@Scope(value=BeanDefinition.SCOPE_PROTOTYPE)
	public IMode myMode(){
		return new MyMode();
	}
}
2、以下是Spring Boot的启动类,以及一个简单的Web Controller,修改自 Getting Started Building a RESTful Web Service
package com;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

package com;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.bean.IService;
import com.bean.MyMode;
import com.bean.IMode;

@RestController
public class GreetingController {

	private static final String template = "Hello, %s!";
	private final AtomicLong counter = new AtomicLong();

	@Autowired
	private IService myService;

	@Autowired
	private IMode mode;

	@RequestMapping("/greeting")
	public Greeting greeting(
			@RequestParam(value = "name", defaultValue = "World") String name) {
		System.out.println(myService.toString());
		System.out.println(mode == myService.getMode());
		mode.print();
		mode.print();

		myService.getMode().print();
		myService.getMode().print();
		return new Greeting(counter.incrementAndGet(), String.format(template,
				name));
	}

	private static class Greeting {

		private final long id;
		private final String content;

		public Greeting(long id, String content) {
			this.id = id;
			this.content = content;
		}

		public long getId() {
			return id;
		}

		public String getContent() {
			return content;
		}
	}
}



 3、运行Application。 

会发现在启动的时候,控制台输出两次:MyMode constructor call。原因有两个Singleton的Bean(MyService和GreetingController)分别注入了MyMode实例,而Singleton默认在启动时实例化,因此必须同时实例化其依赖对象。

在浏览器中输入链接调用greeting方法。输出:

bingo

false

MyMode print call2

MyMode print call2

MyMode print call1

MyMode print call1

这样就违背了初衷,既然是prototype类型的Bean,当然就是希望在每次取时都是不同对象。

在XML配置中需要在MyMode的<Bean>标签中加入子标签<aop:scoped-proxy/>启用代理类,它的默认策略该Bean对应的类存在接口则使用JDK动态代理,否则使用CGLIB。当然也可以用proxy-target-class属性强制指定。

在注解的配置中则是使用@Scope的proxyMode属性,与XML不同地方是这里必须指定代理策略 如果选用Default则默认使用@ComponentScan的代理策略。

4、因此在配置MyMode为@Scope(value=BeanDefinition.SCOPE_PROTOTYPE,proxyMode=ScopedProxyMode.INTERFACES)

再次启动,启动时没有出现MyMode constructor call,说明没有调用MyMode的构造方法。那MyService和GreetingController引用的IMode是什么?

后面再说,调用greeting方法,输出:

bingo

true

MyMode constructor call

MyMode print call1

MyMode constructor call

MyMode print call2

MyMode constructor call

MyMode print call3

MyMode constructor call

MyMode print call4

从上面结果可以看出,MyService和GreetingController引用是一个代理对象,而且是同一个,这个代理对象是singleton的。而每次IMode的方法调用,代理对象都重新生成一个源对象再调用源对象的方法。

5、将MyMode的Scope改为@Scope(value=WebApplicationContext.SCOPE_REQUEST,proxyMode=ScopedProxyMode.INTERFACES)

在重新启动并调用两次,得到结果:

bingotrueMyMode constructor callMyMode print call1MyMode print call1MyMode print call1MyMode print call1

bingotrueMyMode constructor callMyMode print call2MyMode print call2MyMode print call2MyMode print call2

每次request请求一个MyMode实例。

接下来对比XML配置时的运行结果,做一些修改

1、修改Bean配置类,引入XML配置

package com;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;


@Configuration("test")
@ImportResource("classpath:applicationContext.xml")
public class TestBeanConfigration {

	//@Bean
//	public IService myService(){
//		return new MyService(myMode());
//	}

	//@Bean
	//@Scope(value=WebApplicationContext.SCOPE_REQUEST,proxyMode=ScopedProxyMode.INTERFACES)
//	public IMode myMode(){
//		return new MyMode();
//	}
//	

}


2、添加XML配置文件

<?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/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

	<bean id="myService" class="com.bean.MyService" depends-on="myMode">
		<constructor-arg ref="myMode" />
	</bean>

	<bean id="myMode" class="com.bean.MyMode" scope="prototype">
	   <aop:scoped-proxy/>
	</bean>

</beans>

3、启动,一样没有调用MyMode的构造函数。

调用方法输出结果:


bingo
true
MyMode constructor call
MyMode print call
1
MyMode constructor call
MyMode print call
2
MyMode constructor call
MyMode print call
3
MyMode constructor call
MyMode print call
4


当然也可以试试其他Scope,得出结论与上面注解配置表现是一致的(想过去也是一致的,写个例子熟悉下配置)。

Spring Bean生命周期:从启动初始化到优雅销毁的全流程解析 Spring Bean生命周期是IoC容器管理对象创建、依赖注入、初始化与销毁的核心机制。其本质是围绕Bean实例化(Instantiation)、属性填充(Populate Properties)、Aware回调、BeanPostProcessor处理、初始化方法(@PostConstruct/afterPropertiesSet)、销毁方法(@PreDestroy/destroy)等阶段构成的严格时序链路。该机制保障了依赖注入的可靠性、循环依赖的可解性及资源释放的确定性,直接支撑数据库建表、配置热更新、 阅读详情

相关推荐

ESP8266入门(一)固件烧录及常见问题分析

为了实现对数据的远程收集和分析,偶然间发现了esp8266这个模块,对此进行了深入的学习,可是在学习之初遇到了大量的问题,这个系列文章就为大家讲讲我遇到的坑以及解决办法,还有esp8266如何连上oneNet云平台的方法。因为我用的是esp8266nodemcu,可以直接连接usb进行烧录,如果用模块的话接线就比较麻烦,可以去搜搜看.

Jerryxuzherui的博客 8955

@Scope(BeanDefination.SCOPE_PROTOTYPE)

当类被@Scope(BeanDefination.SCOPE_PROTOTYPE)修饰时,说明每次依赖注入时,都会产生新的对象 但是在多线程编程中,如果一个类被@Scope(BeanDefination.SCOPE_PROTOTYPE)修饰,且在另外的对象中如果需要引用此对象时,最好不要使用@Autowired依赖注入,而是使用 ApplicationContext.getBean()的方式去调用。 举例说明: @Component @Scope(BeanDefinition.SCOPE_PROTOTYPE

Emine 1742

U2Net网络实战:从原理到代码实现(附背景去除应用)

本文深入解析了U2Net网络的原理与代码实现,重点剖析了其独特的嵌套U型结构(RSU模块)和显著图融合机制。通过实战演示,指导读者如何加载预训练模型并应用于精准的图像背景去除任务,为电商、摄影等领域提供高效的自动化抠图解决方案。

nn3456的博客 491

Spring容器中scope为prototype类型Bean的回收机制

通过 AutowireCapableBeanFactory 方法 autowireBean 可以将对象装配成 Spring 管理的标准 Bean 对象,主要是用于来填充有注解的属性,这样才可以使用 Spring 的 DI 特性。通过代码 new 出来的对象使用 AutowireCapableBeanFactory 方法 autowireBean 填充属性成为标准 Spring Bean 后不用担心内存溢出的问题,本质上和 Spring prototype Bean 的回收机制一样,使用完就有可能被

聚焦AI技术前沿,深度解析大模型原理与多场景应用,探索最新突破与落地实践,助力行业洞悉趋势,驱动智能转型,赋能千行百业。 1062

UCIe相关开源项目记录

目前找到的和UCIe协议有关的5个开源项目,如果也有正在做的朋友,欢迎私信交流

m0_64102565的博客 823

【初阶】手把手教你轻松上手Denodo | 连接数据库并创建基本视图 (二)

在本教程的第二部分,我们将涵盖:连接到数据库,与创建基本视图。

Denodo的博客 1104

Spring之作用域

1111111111

u013401975的博客 318

Python爬虫实战:实时监控美国SEC官网文件更新,助你第一时间掌握市场动态

在资本市场中,信息就是财富。美国证券交易委员会(SEC)官网公开了大量公司披露文件,涵盖财报、招股说明书、内幕交易等重要信息。对投资者、分析师及法律合规人员来说,实时监控这些公开文件具有重要价值。

2201_76125261的博客 594

@Scope(“prototype“)的正确用法——解决Bean的多例问题

1. 问题,Spring管理的某个Bean需要使用多例   在使用了Spring的web工程中,除非特殊情况,我们都会选择使用Spring的IOC功能来管理Bean,而不是用到时去new一个。Spring管理的Bean默认是单例的(即Spring创建好Bean,需要时就拿来用,而不是每次用到时都去new,又快性能又好),但有时候单例并不满足要求(比如Bean中不全是方法,有成员,使用单例会有线程安全问题,可以搜索线程安全与线程不安全的相关文章),你上网可以很容易找到解决办法,即使用@Scope("prot

宇智波小强的博客 3239

OPC UA协议深度解析 + C#跨平台实战:无缝对接西门子S7-1200/1500 PLC

本文完成了OPC UA协议深度解析→西门子PLC服务端配置→C#跨平台客户端开发→全平台部署拆解OPC UA核心模型与安全机制,从原理层面理解工业标准化通信逻辑基于官方SDK开发工业级客户端,支持读写、订阅、证书管理、心跳保活核心功能实现Windows、Linux、统信UOS全平台兼容,满足工控系统国产化改造刚需提供完整的优化方案与踩坑指南,可直接落地商用项目。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 518

数据分享|1961-2017年中国0.25°×0.25° 逐日地表水文数据集(VIC-CN05.1)

其中,全球径流中心(University of New Hampshire and Global Runoff Data Centre, UNH/GRDC)的复合产流场集成了观测的河道径流和水量平衡模式模拟的地表和地下径流,常被用来评估模拟的径流。在长白山、海北灌丛和千烟洲通量站,模拟与观测的逐月潜热通量的平均NSE为0.61。VIC-CN05.1受益于较准确的大气驱动场、先进的地表水文参数化方案以及更真实丰富的土壤信息,可作为中国水文气象研究的参照数据,用于陆面模式的评估和长期的趋势分析等。

J_Giser的博客 1831

Spring的@Scope注解prototype

因为A是单例,所以注入的属性B相当于也是单例了。即:A中的B是固定不变的了,每次调用a.printB,输出b都是一样的。那么如果想要每次调用a.printB,输出b都不一样,就需要使用代理proxyMode这样每次调用b.toString()的时候就会通过代理new一个b。

liaonanfeng88的优快云博客 1275

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

IDEA中Maven配置Spring框架:从环境搭建到依赖注入实战

依赖注入是现代Java企业级开发的核心设计模式,它通过将对象依赖关系的控制权从代码内部转移到外部容器,实现了组件间的解耦。这一原理在Spring框架中通过IoC容器得以实现,极大地提升了代码的可测试性和可维护性。在工程实践中,Maven作为标准的项目构建与依赖管理工具,通过POM模型和中央仓库机制,自动化地解决了库文件下载、版本管理和传递性依赖等复杂问题。对于需要在IntelliJ IDEA中搭建Spring开发环境的开发者而言,理解Maven的依赖管理机制与Spring的IoC容器原理是成功配置的关键。本

weixin_30565327的博客 418

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Spring Framework精讲之二:Spring Bean

Spring bean的相关概念,帮助您快速入门

182

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Spring Bean作用域的设计与使用

Spring Bean作用域设计与使用要点 Spring提供了6种bean作用域,但实际项目中90%以上使用默认的singleton。理解作用域设计的关键在于回答三个问题:是否需要共享实例?共享范围多大?生命周期跟随谁? Singleton:默认作用域,适用于无状态服务对象,容器缓存单实例,高效复用 Prototype:解决状态隔离问题,每次获取新实例,但需注意注入singleton时的陷阱 Web相关作用域:request/session/application/websocket,专为Web环境设计 特

Sam_Deep_Thinking 566

全网最强Spring教程 | 万字长文爆肝Spring(一)

本文介绍了Spring框架的基本概念和学习路线。主要内容包括: 为什么要学习Spring:Spring是企业开发必备技能,具有简化开发和框架整合两大优势,市场占有率超过90%。 学习内容:重点学习IOC/DI、AOP、事务处理和整合MyBatis这四部分核心技术。 Spring系统架构:包括核心容器、AOP、数据访问和Web等模块,其中IOC和AOP是基础。 核心概念:解释了IOC(控制反转)、DI(依赖注入)和Bean等Spring核心思想。 学习路线:从理解设计思想开始,通过基础操作体会思想,最终通过案

qq_45832461的博客 1248

Spring Framework中文官方文档的价值与使用技巧

Spring Framework作为Java生态中核心的企业级开发框架,其官方文档是开发者不可或缺的参考资料。依赖注入(DI)和控制反转(IoC)是Spring的核心机制,通过统一术语和版本同步,中文官方文档为国内开发者降低了学习门槛。文档内容涵盖从基础概念到最佳实践的全方位指导,特别在解决版本升级、性能优化和安全漏洞等实际工程问题时表现出色。针对CVE-2024-38819等安全漏洞,文档提供了详细的防护方案。掌握高效的文档搜索策略和本地化部署方法,能显著提升开发效率。

weixin_30887919的博客 561

Spring 面经系列 · 第 2 篇:Bean 循环依赖与三级缓存,二级缓存到底行不行?

两个 Bean 互相引用,Spring 靠三级缓存把环拆开:L1 成品、L2 半成品、L3 的 ObjectFactory。这题的分水岭是「为什么非要三级,二级行不行」——答案是提前暴露的代理,以及它和最终对象的一致性怎么收口。本篇沿 getBean 的实际调用链讲清环在哪一步闭合、L3 何时被执行第二次,再补两种 Spring 救不了的环,最后从并发视角解释 singletonObjects 的加锁范围与 this 逃逸。

OxYGC 781

【大白话说Java面试题 第154题】【06_Spring篇】第14题:Spring 支持的 Bean 作用域

摘要: Spring Bean 作用域是面试核心考点,涉及六种作用域及其底层实现机制。singleton(默认)全局单例,需注意线程安全;prototype每次创建新实例,但需手动管理销毁避免内存泄漏;Web作用域(request、session、application、websocket)依赖上下文监听器绑定生命周期,需通过代理(如ScopedProxyMode.TARGET_CLASS)解决跨作用域注入问题。重点考察源码级理解(如DefaultListableBeanFactory管理机制)及生产场景选

Java后端 | AI智能体应用实战派 | 电脑技能行家 360

Spring系列——两万字长文教会你Spring (超详细!!!)

到此,我们学习完了 Spring 框架,包括: Spring 体系结构 Spring Bean Spring AOP Spring JDBC Spring 事务管理 写此文章是为了做个笔记,等以后自己忘记了可以回头快速上手。同时也分享给小伙伴们,希望我们都能越来越好,不会就学 B 站,不懂就问 AI,总好过自己两耳不闻窗外事的独自琢磨。 最后认识一下吧,笔者叫`北迁`,hhh~~。

weixin_63009611的博客 1181

Spring核心核心原理与基础实操完整详解

System.out.println("业务方法执行:用户保存成功");

y932639782的博客 187

Spring IoC与DI核心原理及实践指南

控制反转(IoC)和依赖注入(DI)是现代Java开发的核心设计模式,通过将对象创建和依赖管理的控制权交给容器,实现了组件间的松耦合。Spring框架作为Java生态中最流行的IoC容器,提供了完整的DI实现方案。从技术原理看,IoC容器通过Bean生命周期管理、依赖解析和自动装配等机制,大幅提升了代码的可测试性和可维护性。在实际工程中,Spring支持构造器注入、Setter注入等多种DI方式,并结合XML、注解和Java配置等元数据形式,满足不同场景需求。特别是在微服务架构下,Spring IoC与云原

weixin_34023982的博客 376

Spring Bean生命周期深度解析:从源码到线上故障排查

Spring Bean生命周期是Java工程师理解Spring框架的核心基础概念,它定义了Bean从定义、实例化、依赖注入、初始化回调到销毁的完整时序过程。其底层原理涉及BeanDefinition注册、三级缓存解决循环依赖、BeanPostProcessor扩展点、AOP代理织入时机等关键机制。该模型不仅支撑@Transactional、@Async、@EventListener等核心功能的正确性,更直接影响应用启动稳定性、资源释放安全性和云原生就绪状态。掌握其执行阶段(如postProcessBefor

weixin_34110749的博客 413

Spring Framework源码解析——BeanDefinition

本文深入剖析了Spring框架中的核心组件BeanDefinition,它是描述Bean元数据的统一模型,作为连接配置与运行时对象的桥梁。文章从设计目标、接口层级、核心方法及字段展开,详细解析了BeanDefinition如何解耦配置与实例化,支持动态注册修改,并提供完整的元数据支持。通过分析AbstractBeanDefinition等实现类,阐述了Spring容器实现依赖注入、AOP代理等功能的底层机制,揭示了BeanDefinition在IoC容器中的核心地位。

谷哥的小弟 1195
下一篇: @Bean在@Configuration和在@Component中的区别
ttjxtjx
博客等级 码龄15年 6粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值