spring中expose-proxy的作用与原理

Docker端口暴露与发布原理:EXPOSE和-p的本质区别 Docker端口管理是容器网络的核心基础概念,其本质源于Linux Network Namespace隔离机制。EXPOSE仅作镜像元数据声明,不触发任何内核操作;而publish(-p)才真正配置iptables DNAT规则,实现宿主机到容器的流量转发。这一原理差异直接决定服务是否可被外部访问,也是DevOps部署失败、CI/CD流水线超时、Kubernetes服务发现异常等高频问题的底层根源。在微服务架构、SaaS平台容器化及边缘计算场景中,精准控制端口暴露范围,结合127.0.0.1绑定、反向代理分 阅读详情

先看一下几个问题,下面是段代码:

public interface UserService{
	public void a();
	public void a();
}

public class UserServiceImpl implements UserService{
	@Transactional(propagation = Propagation.REQUIRED)
	public void a(){
		this.b();
	}
	@Transactional(propagation = Propagation.REQUIRED_NEW)
	public void b(){
		System.out.println("b has been called");
	}
}

ps:代码参照《Spring源码解析》p173页。
Q1:b中的事务会不会生效?
A1:不会,a的事务会生效,b中不会有事务,因为a中调用b属于内部调用,没有通过代理,所以不会有事务产生。
Q2:如果想要b中有事务存在,要如何做?
A2:<aop:aspectj-autoproxy expose-proxy=“true”> ,设置expose-proxy属性为true,将代理暴露出来,使用AopContext.currentProxy()获取当前代理,将this.b()改为((UserService)AopContext.currentProxy()).b()

下面看下expose-proxy在spring中的作用:

在AopNamespaceUtils中的方法

public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
	BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		//处理proxy-target-class与expose-proxy属性
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		registerComponentIfNecessary(beanDefinition, parserContext);
	}

在这里插入图片描述
在这里插入图片描述
跟踪代码至此,发现蓝色部分代码这里将该参数设置到了BeanDefinition中,那么这个参数在哪里使用的呢。跳过aop生成代理的过程,直接看代理的调用的地方,以JdkDynamicAopProxy为例,cglib方式的地方与jdk一致。对JDK方式的动态代理,都是通过invoke方法执行目标对象的方法,那么来看一下spring中JdkDynamicAopProxy的invoke方法源码。

/**
	 * Implementation of {@code InvocationHandler.invoke}.
	 * <p>Callers will see exactly the exception thrown by the target,
	 * unless a hook method throws an exception.
	 */
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MethodInvocation invocation;
		Object oldProxy = null;
		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		Class<?> targetClass = null;
		Object target = null;

		try {
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return hashCode();
			}
			if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;

			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// May be null. Get as late as possible to minimize the time we "own" the target,
			// in case it comes from a pool.
			target = targetSource.getTarget();
			if (target != null) {
				targetClass = target.getClass();
			}

			// Get the interception chain for this method.
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// Check whether we have any advice. If we don't, we can fallback on direct
			// reflective invocation of the target, and avoid creating a MethodInvocation.
			if (chain.isEmpty()) {
				// We can skip creating a MethodInvocation: just invoke the target directly
				// Note that the final invoker must be an InvokerInterceptor so we know it does
				// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
			}
			else {
				// We need to create a method invocation...
				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				retVal = invocation.proceed();
			}

			// Massage return value if necessary.
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				// Special case: it returned "this" and the return type of the method
				// is type-compatible. Note that we can't help if the target sets
				// a reference to itself in another returned object.
				retVal = proxy;
			}
			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
				throw new AopInvocationException(
						"Null return value from advice does not match primitive return type for: " + method);
			}
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

在这里插入图片描述
在这里插入图片描述
主要关注这两段代码,发现如果expose-proxy属性值为true的话会调用
oldProxy = AopContext.setCurrentProxy(proxy);
那么看一下这个方法
在这里插入图片描述
在这里插入图片描述
通过英文注释应该就大概明白了,这里是通过一个ThreadLocal来保存代理的,在每次调用代理的时候会判断一下exposeProxy是否为true,如果是的话,就通过ThreadLocal保存代理,可通过以下方法获取到代理。
在这里插入图片描述
然后invoke方法的finally块里又把oldProxy放回了ThreadLocal中,这里要注意一下,就是每次调用都会set一下当前的代理,最后再把之前保存的放回去。

那么之前在问题中,a中调用b的时候通过从ThreadLocal中获取到当前代理再执行b方法就可以达到b中也有事务的要求了。简单来说,处理的方法就是设置expose-proxy属性为true暴露代理。

思澈sdk-新建lcd co5300至此有3个同ID的驱动,在co5300xxxx.c的LCD_DRIVER_EXPORT(co5300, LCD_ID, &lcdc_int_cfg, &CO5300_drv, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT, 2);2 在customer\peripherals\Kconfig_lcd中添加如下配置(注意修改的地方有两个LCD_USING_TFT_CO5300_143)5 在该文件中的config LCD_DPI配置项下添加:(这里300为DPI) 阅读详情

相关推荐

使用C++编写一个可视化窗口

初学C++时,控制台会给我们提供一个黑窗口,而这篇文章所做的就是:创建一个属于图形界面窗口,而不是使用控制台黑窗口 如图,这是一个标题为XSZY的窗口 看完这篇文章,你想要的窗口大小,图标等都可以自己定义 甚至是在窗口上鼠标的样子,都是可以随意改的 所有有关视窗的基本函数和类型都定义在头文件 <windows.h> 中 我们只需要引用就好了 //引用头文件 windows.h #include<windows.h> 然后定义程序的入口函数main int __stdcall W

XSZY_的博客 6万+

spring---aop(7)---Spring AOP中expose-proxy介绍

写在前面   expose-proxy。为是否暴露当前代理对象为ThreadLocal模式。   SpringAOP对于最外层的函数只拦截public方法,不拦截protected和private方法(后续讲解),另外不会对最外层的public方法内部调用的其他方法也进行拦截,即只停留于代理对象所调用的方法。 案例分析 public class AServiceImpl impl...

weixin_30593261的博客 580

接入穿山甲SDK时,Unity打Android包报错日志

SDK工程设置为Enable,项目工程设置为Disable。2、将unitypackage导入包名为:com.DefaultCompany.Myproject的另一个工程,打包报错。3、点击工程默认弹出Enable Android Auto-resolution 设置选项,点击Enable。1、新建一个空工程,设置包名为:com.ceshi.hewen,正常打包无报错,导出unitypackage。2、点击Reset to Defaults 重置参数,再点击ok关闭设置窗口。

不文不武的禾文 3583

【spring事务】 --- exposeProxy属性的作用 --- 同一个对象里方法间调用事务传播行为生效的方法

文章目录1 先看现象2 从源码看一下exposeProxy在事务源码中的逻辑3 解决方式 源码地址:https://github.com/nieandsun/spring-study 1 先看现象 有如下代码,调用addUserAndSalary方法,t_user表和t_salary表哪个表里会被插入数据呢??? @Service public class UserServiceImpl i...

nrsc 2576

【重磅更新】CT/MRI LI-RADS 2024:肝细胞癌局部区域治疗后反应评估的核心突破与临床实践指南

减少过度治疗:辐射 LRT 的 Nonprogressing 类别避免了 “持续强化 = 存活” 的误判,降低不必要的再治疗风险;提高检出效率:非辐射 LRT 的辅助特征升级减少了 Equivocal 比例,更早识别存活肿瘤;统一评估语言:标准化的分类标准为放射科、肝病科、肿瘤科、肝移植科的多学科协作(MDT)提供了统一 “沟通工具”,助力治疗方案的精准制定。

楚山之石的博客 1225

基于ResNet-50的猫狗分类训练

基于ResNet-50的猫狗分类python训练

weixin_46352497的博客 1004

从@Async案例找到Spring框架的bug:exposeProxy=true不生效原因大剖析+最佳解决方案【享学Spring】

前言 从本文标题就能看到靓丽的字眼:Spring框架bug。相信有的小伙伴心里小九九肯定会说:又是一篇标题党文章。此处可以很负责人的告诉大家:本人任何文章绝不哗众取宠,除了干货还是干货。 相信关注过我的小伙伴都是知道的,我只递送干货,绝不标题党来浪费大家的时间和精力~那无异于谋财害命(说得严重了,不喜勿喷) 本篇文章能让你知道exposeProxy=true真实作用实际和作用范围,从而能够更精...

架构师:通透,才能写出好代码! 5660

模型量化必知:Per-Tensor和Per-Channel到底怎么选?

本文深入解析了模型量化中Per-Tensor与Per-Channel两种核心策略的抉择。Per-Tensor量化实现简单、硬件兼容性极佳,适合激活值或分布均匀的权重;而Per-Channel量化精度更高,能更好地处理权重分布不均的卷积层,是现代CNN权重量化的主流。文章提供了从硬件平台、数值分布到精度需求的实战决策框架,并推荐了“权重Per-Channel,激活Per-Tensor”的混合量化最佳实践。

assembly8low的博客 983

Spring expose-proxy的作用与原理

XX

每天进步一点点 871

bugku渗透测试4-writeup

三、对这个主机进行全端口的扫描,发现存在22000 ssh端口,那么可以联想到时redis写入公钥来连接主机。又来了一个新的靶场,这个靶场打下来我觉得关键就是信息收集,走了很多的弯路。八、最后一个flag是要去看cms的数据库里面,这个数据库是sqlite。把这个数据库下载下来,登录密码是加密的,就直接用token。一、入口的漏洞是在登录的时候去抓包,修改action的值。六、没想到这个第一台机器的密码,在第二台里面。七、扫描第一台主机、使用之前的密码连接成功。获取最后一台主机的root密码。

vsdfbhsdhsdfh的博客 1295

【WorkBuddy专栏61】字节的AI打法为什么一直在变——WorkBuddy/CodeBuddy vs 字节Trae/TRAE Work/豆包全维度对比

【WorkBuddy专栏61】字节的AI打法为什么一直在变——WorkBuddy/CodeBuddy vs 字节Trae/TRAE Work/豆包全维度对比

AI人人懂 2749

【proxyConfig源码分析】【proxyTargetClass】【exposeProxy】

本文转载自shysheng:spring proxyConfig源码分析 我们知道,ProxyConfig是所有产生Spring AOP代理对象的基类,它是一个配置源,主要为其AOP代理对象工厂实现类提供基本的配置属性。 它一共包含5个属性,本文主要就是分析这5个属性在产生代理对象过程中的具体作用。 ProxyConfig包含的5个属性如下: public class ProxyConfig ...

wt_better的博客 1867

2万字大厂面经:小米嵌入式面试题及参考答案(持续更新)

BIOS (Basic Input/Output System) 是一种存储在ROM中的固件程序,它为计算机提供了最基础的硬件初始化和服务。BIOS主要存在于传统的x86架构计算机中。嵌入式系统的启动流程取决于具体的硬件平台和所采用的操作系统。复位阶段:当系统通电或复位时,CPU进入复位状态。硬件初始化:CPU和必要的硬件设备(如内存控制器)被初始化。加载引导加载程序:引导加载程序(如U-Boot)被加载到内存中。执行引导加载程序:引导加载程序开始执行,初始化更多的硬件设备,并检测存储介质。

大模型大数据攻城狮的专栏 2529

@Transacitonal注解不生效之spring中expose-proxy的作用与原理

几年前记得整理过,@Transacitonal注解的方法被另外一个方法调用的时候,事务是不生效的。 如果大量代码已经这么写了,这个时候抽取出去不现实,怎么办呢? 答案就是在&lt;aop:aspectj-autoproxy /&gt;中设置expose-proxy属性为true暴露代理。如下: &lt;aop:aspectj-autoproxy expose-proxy=“true”&gt; ,然...

weixin_34082695的博客 779

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Spring AOP 源码分析之入口

目录 一、@EnableAspectJAutoProxy 1.1 proxy-target-class 1.2 expose-proxy 1.3 AspectJAutoProxyRegistrar 二、AnnotationAwareAspectJAutoProxyCreator 2.1 AopConfigUtils 2.2 APC类型的介绍 2.3 APC 的注册 2.4 总结 ...

wyfvsfy的博客 1016

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Spring AOP 源码分析 - 拦截器链的执行过程

1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程。现在我们的得到了 bean 的代理对象,且通知也以合适的方式插在了目标方法的前后。接下来要做的事情,就是执行通知逻辑了。通知可能在目标方法前执行,也可能在目标方法后执行。具体的执行时机,取决于用户的配置...

dishitu6229的博客 825

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Spring| Spring中的动态代理配置(aspectj-autoproxy属性介绍)

一. Spring中的代理 JDK动态代理: 其代理对象必须是某个接口的实现,它是通过运行期间创建一个接口的实现类来完成对目标对象的代理. CGLIB代理: 实现原理类似于JDK的动态代理,只是它在运行期间生成目标类扩展的子类对象.(也就是通过继承的方式创建的代理类).CGLIB是高效的代码生成包,底层是依靠ASM(开源的Java字节码编辑类库)操字节码实现的,性能比JDK强. 基于注解...

YvesHe的专栏 6068

SpringAOP笔记整理

我们都知道,想使用SpringAop需要做一些xml配置,其中很大一部分是基于标签的,这些标签并不是Spring原生,而是自定义注解。Spring中如果声明了自定义注解,那么就一定会在程序中的某个地方注册了对应的解析器。我们的分析也是由此开始。 我们全局搜索后发现了AopNamespaceHandler类,点进去看下: public class AopName...

qq_38762479的博客 497

Spring AOP中expose-proxy介绍

https://www.cnblogs.com/chihirotan/p/7356683.html   写在前面   expose-proxy。为是否暴露当前代理对象为ThreadLocal模式。   SpringAOP对于最外层的函数只拦截public方法,不拦截protected和private方法(后续讲解),另外不会对最外层的public方法内部调用的其他方法也进行拦截,即只停留于...

z69183787的专栏 6287

从源码看 Spring AOP 如何生效:`<aop:aspectj-autoproxy/>` 标签解析与自动代理创建器注册机制

在 Spring 框架中,只需要在 XML 配置文件里写上一行 `<aop:aspectj-autoproxy/>`,基于注解的 Spring AOP 能力就会被激活。这背后隐藏着一条清晰的源码链路:XML 命名空间标签 → 标签解析器(`BeanDefinitionParser`)→ 自动代理创建器(AutoProxyCreator)的注册与属性装配。本文以 [source-code-hunte

gitblog_00337的博客 1077

Spring AOP的实现原理之<aop:aspectj-autoproxy />的解析

本文主要针对注解形式的AOP作分析,j

3万+

Spring 与代理有关属性详解

大家都知道Spring AOP,也知道使用自动代理需要有如下简单配置:<aop:aspect-autoproxy /><!-- 就是如此简单 -->但是知道proxy-target-class 以及 expose-proxy 属性的作用吗? - proxy-target-class: 强调spring 应该使用那种代理方式:JDK动态代理和CGLIB - 强制使用CGLIB代理会出现以

Genge 4198

Spring源码之动态AOP

支持aop注解 <aop:aspectj-autoproxy /> 创建解析器进行解析 public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { BeanDefinition b...

liyingzhe 152

Spring AOP 开发实践

本文摘要: Spring AOP开发实践详解: AOP是面向切面编程,通过横向抽取通用逻辑(如日志、事务)来补充OOP,实现不修改源码增强方法功能。 两种代理机制: JDK动态代理要求目标类实现接口,基于接口生成代理 CGLIB代理可代理无接口类,通过子类继承实现,但无法代理final类/方法 Spring默认按目标类是否有接口自动选择代理方式,高版本SpringBoot默认强制CGLIB 通过完整代码示例演示了两种代理的实现: JDK代理通过InvocationHandler拦截接口方法 CGLIB利用E

py_1990_04_20的博客 329

Spring中的两种代理模式的实现原理

代理模式 Jdk动态代理 通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类,被代理的对象必须实现了某一个接口。 public <T> T getProxy(T target) { return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.ge

zhouyu5408的博客 2046
上一篇: 总结
JustForSS
博客等级 码龄13年 7粉丝 15原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值