当用AopContext.currentProxy()方式调用@Asyn注解的方法,发现不起作用了

news2024/11/27 13:43:53

1、前言

遇到到平常一些spring相关调用错误浅浅记录下

2、我们常常会用到在一个类的方法内部会去调用本类的别一个方法

我们常常会用到在一个类的方法内部会去调用本类的别一个方法,示例如下:

public interface ITestAsy {
    String funttion1();
    String function2();
}

@Component
public class TestAsy implements ITestAsy {
 @Override
    public String funttion1() {
        this.function2();
        return "1";
    }

    @Override
    public String function2() {
        return "2";
    }
}

上面都是普通方法,调用完全没问题,
但后来function2可能执行时间很长,funttion1在调用funttion2时不用等待funttion2的返回,那么我们是不是想到用另一个线程去调用function2。
而spring给我们提供了注解@Async,可以很容易实现

2.2 用@Async实现对方法的异步调用

我们知道@Async是会给这个类生成一个代理的,实在代理类中会会将这个方法打包成一个callAble 提交给线程池,这样spring就帮我们实现了只需通过注解的方式 就可以异步调用的目的。
如果我们这样调:

 @Test
public void ttttt(){
        System.out.println(Thread.currentThread().getName());
        iTestAsy.function2();
    }

打印线程如下:

main
SimpleAsyncTaskExecutor-1

说明调用iTestAsy.function2();另起了一个线程调用。

如果我们需在funtion1中去调用funciton2呢,这样写行不行?

 @Override
public String funttion1() {
        System.out.println(Thread.currentThread().getName());
        this.function2();
        return "1";
}

可以看下测试效果:

@Autowired
private ITestAsy iTestAsy;

@Test
public void ttttt(){
    System.out.println(Thread.currentThread().getName());
    iTestAsy.funttion1();
}

打印如下:

main
main
main

说明this.function2(); 这里this 不是代理对象自然不行。
换种写法,通过spring上下文来获取这个对象实例 然后再调用funciton2,如下:

@Override
public String funttion1() {
    System.out.println(Thread.currentThread().getName());
    ITestAsy bean = applicationContext.getBean(ITestAsy.class);
    bean.function2();
    return "1";
}

打印如下:

main
main
SimpleAsyncTaskExecutor-1

funtion2的调用在另一个想成中。@Aync注解起作用了。
而除了通过applicationContext获取对象去调这个方法外,还有一种方式,就是通过获取绑定在本线程上的代理对象 来调用这个方法

2.3、用AopContext.currentProxy();获取本实例的代理对象 来调用带@Aync注解的方法

代理实例如下:

  @Override
 public String funttion1() {
      System.out.println(Thread.currentThread().getName());
      ITestAsy bean = (ITestAsy) AopContext.currentProxy();
      bean.function2();
      return "1";
  }

调用发现报错如下:
在这里插入图片描述
让我们开启exposeProxy = true,于是我们在类上另上注解:

@EnableAsync
@EnableAspectJAutoProxy(exposeProxy =  true)
@Configuration
public class TestConfig {


}

再继续调用,还是报错:
java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
如果在function1上加上@Transactional注解,调用成功了
如下:

@Override
@Transactional
public String funttion1() {
    System.out.println(Thread.currentThread().getName());
    ITestAsy bean = (ITestAsy) AopContext.currentProxy();
    bean.function2();
    return "1";
}
@Async
@Override
public String function2() {
    System.out.println(Thread.currentThread().getName());
    return "2";
}

main
main
SimpleAsyncTaskExecutor-1

2.4、为什么用用AopContext.currentProxy();调用@Asyn注解的方法 还是报错,而在这个方法上加上@Transactional注解就不报错了

为什么用用AopContext.currentProxy();调用@Asyn注解的方法 还是报错,而在这个方法上加上@Transactional注解就不报错了,那么需要看下@Asyn 生成的代理和@Transactional代理有什么不一样。
一定是@Transactional 设置了exposeProxy = true,所以不报错了。

2.5、看下AopContext

public final class AopContext {

	private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<>("Current AOP proxy");


	private AopContext() {
	}


	public static Object currentProxy() throws IllegalStateException {
		Object proxy = currentProxy.get();
		if (proxy == null) {
			throw new IllegalStateException(
					"Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.");
		}
		return proxy;
	}

	
	@Nullable
	static Object setCurrentProxy(@Nullable Object proxy) {
		Object old = currentProxy.get();
		if (proxy != null) {
			currentProxy.set(proxy);
		}
		else {
			currentProxy.remove();
		}
		return old;
	}

}

发现只有currentProxy.get() 获取到值后,才不会报出异常,那么也就是说必须调用setCurrentProxy这个方法。
我们是通过@EnableAspectJAutoProxy(exposeProxy = true)这个注解来使得支持AopContext.currentProxy()调用方式,那么我们先看下这个注解的作用

2.6、@EnableAspectJAutoProxy(exposeProxy = true)注解的作用

@EnableAspectJAutoProxy(exposeProxy = true) 它导入了@Import(AspectJAutoProxyRegistrar.class)

public abstract class AopConfigUtils {
	public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
		}
	}
	public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
		}
	}
}

这个注解标注的属性最终都被设置到了internalAutoProxyCreator 这个bean上,这是什么bean

2.7、internalAutoProxyCreator

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/753199.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pycharm新建分支并提送至GitHub

文章目录 前言pycharm创建本地分支Push至远程分支 前言 当我们写的项目代码越来越多时&#xff0c;一个master分支无法满足需求了&#xff0c;这个时候就需要创建分支来管理代码。 创建分支可以快速的回滚到某个节点的版本&#xff0c;也可以多个开发者同时开发一个项目&#…

css:横向滚动布局

效果&#xff1a; 实现代码&#xff1a; <template><div class"index_div"><div class"container"><div class"flexBox"><div class"flex_item" v-for"item in topMenu" :key"item.id&quo…

五种不同自动化测试模型的基本介绍

随着移动互联网的发展&#xff0c;软件研发模型逐步完善&#xff0c;软件交付质量越来越受到软件公司的重视&#xff0c;软件测试技术特别是自动化测试技术开始在软件系统研发过程中发挥着越来越重要的作用。 与传统的手工测试技术相比&#xff0c;自动化测试具备了良好的可操…

模拟实现浏览器自带的 ctrl+f 搜索功能

主要利用的就是元素的innerHtml&#xff0c;通过replace方法&#xff0c;把文本替换为带标签的文本&#xff0c;然后就有样式了 下图贴出 主要代码及效果 <template><div class"search-page"><el-input style"width: 200px" v-model"…

2023年信号处理与机器学习国际研讨会(WSPML 2023)| SPIE独立出版 快速稳定

会议简介 Brief Introduction 2023年信号处理与机器学习国际研讨会(WSPML 2023) 会议时间&#xff1a;2023年9月22 -24日 召开地点&#xff1a;中国杭州 大会官网&#xff1a;www.wspml.org 2023年信号处理与机器学习国际研讨会(WSPML 2023) 由西安交通大学、重庆大学光电技术及…

【学术小白如何写好论文】研究结论:结论vs结论

文章目录 一、引言二、研究结论的重要性三、研究结论的切入口&#xff08;1&#xff09;这个结论与前人研究的对话&#xff08;2&#xff09;这个研究结果本身的意义所在 四、注意事项&#xff08;1&#xff09;清楚区别&#xff08;2&#xff09;对结论的深入解析&#xff08;…

Lua脚本本地调试

这里主要使用日志的方式进行debug 环境依赖 项目对openresty包的依赖比较高&#xff0c;所以环境基础都在openresty下进行 openresty的使用 openresty下载地址 下载完成后解压&#xff0c;具体使用方式和nginx没有什么区别&#xff0c;主要依赖文件是一下几个 nginx.exe …

qt开发技巧之嵌入式linux点击触发两次

1.问题 移植qt5.12.9到嵌入式linux系统&#xff0c;tslib作为触摸输入&#xff0c;开发平台是imx6ull&#xff0c;点击pushbutton按钮会出现触发两次点击的情况。 2.解决 vi /etc/profile&#xff0c;在 /etc/profile里添加环境变量&#xff0c;禁止QT自带输入检测&#xff0…

数据结构---手撕图解堆的实现和TopK的应用

文章目录 重要的概念树的存储方式顺序存储链式存储 堆的概念堆的实现向上调整算法一些实现过程中的技巧实现搭建堆实现出堆的操作向下调整算法 堆排序TopK 重要的概念 要讲到堆&#xff0c;先要说两个关于二叉树的概念 满二叉树&#xff1a;一个二叉树如果每一层的节点数都是最…

ylb_学习笔记02

1.随机4位数&#xff1a; String random RandomStringUtils.randomNumeric(4);System.out.println("注册验证码的随机数 random"random);2.使用http时判断响应的状态为ture&#xff08;200&#xff09;&#xff1a; response.getStatusLine().getStatusCode() Htt…

在阿里云linux上安装MySql数据库

我们先远程连接服务器 然后输入 sudo yum update重新运行一下 然后 sudo yum install mysql-server安装 mysql 服务 其中有两次 y n 选择 都选y就好了 然后 运行 sudo service mysqld start启动MySql 然后 我们查看一下MySql sudo service mysqld status

谷歌浏览器,网站多账号登陆的方法

在测试系统某些功能的时候&#xff0c;不同的模块&#xff0c;需要不同的权限&#xff0c;所以需要登陆不同的账号&#xff0c;以下有两种办法&#xff0c;可以快速切换账号方便进行测试。 1&#xff0c;使用SessionBox插件 SessionBox是一款可以方便地切换网站的session&…

Android开发笔记

一、知识点 1、Notification 通知的创建流程 1&#xff09;创建一个NotificationManager&#xff0c;获取系统服务&#xff0c;getSystemService()方法&#xff1b; 2&#xff09;使用Builder构造器来创建Notification对象&#xff0c;设置通知的各种属性&#xff1b; 3&#…

postgresql还原bak

1、第一步肯定是要新建自己还原的目标数据库&#xff0c;例如&#xff1a; 2、进入postgresql的安装目录下的bin目录下 然后地址栏输入cmd进入命令 输入以下 psql -h localhost -U postgres -p 5432 -d SamsinoYardStandard_karamay -f "D:\desktop\zk\20230628.bak&quo…

CEO对今天的CIO们真正的要求是什么?

在当今数字化和信息时代&#xff0c;企业的首席信息官&#xff08;CIO&#xff09;的角色变得至关重要。CIO不仅需要具备深厚的技术知识&#xff0c;还需要在商业战略、创新和领导力方面展现出卓越的能力。作为企业的首席执行官&#xff08;CEO&#xff09;&#xff0c;他们对C…

【Distributed】分布式Ceph存储系统

文章目录 一、存储基础1. 单机存储设备1.1 DAS1.2 NAS1.3 SAN1.4 单机存储的问题1.5 商业存储解决方案 2. 分布式存储&#xff08;软件定义的存储 SDS &#xff09;分布式存储的类型 3. Ceph 简介4. Ceph 优势5. Ceph 架构6. Ceph 核心组件7. OSD 存储后端7.1 Filestore7.2 Blu…

单轴机器人的结构与特点

单轴机器人是由马达驱动的移动平台&#xff0c;由滚珠螺杆和 U型线性滑轨导引构成&#xff0c;其滑座同时为滚珠螺杆的驱动螺帽及线性滑轨的导引滑块&#xff0c;可用半导体、光电、交通运输业、环保节能产业、精密工具机、机械产业、智慧自动化、生技医疗上。 相对于传统的模组…

Yalmip工具箱使用教程(1)-入门学习

博客中所有内容均来源于自己学习过程中积累的经验以及对yalmip官方文档的翻译&#xff1a;YALMIP 1.Yalmip工具箱的下载与安装 1.1下载 Yalmip的作者是Johan Lfberg&#xff0c;是由Matlab平台编程实现的一个免费开源数学优化工具箱&#xff0c;在官网上就可以下载。官方下载…

LeetCode 0931. 下降路径最小和:通俗思路讲解

【LetMeFly】931.下降路径最小和&#xff1a;通俗思路讲解 力扣题目链接&#xff1a;https://leetcode.cn/problems/minimum-falling-path-sum/ 给你一个 n x n 的 方形 整数数组 matrix &#xff0c;请你找出并返回通过 matrix 的下降路径 的 最小和 。 下降路径 可以从第一…

LeetCode 142.环形链表II

142. 环形链表 II - 力扣&#xff08;LeetCode&#xff09; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/ class Solution { public:ListNode *detectCycle(ListNode …