解决spring AOP中自身方法调用无法应用代理的问题
时间:2022-02-01 10:17:55|栏目:JAVA代码|点击: 次
spring AOP中自身方法调用无法应用代理
如下例
public class MyServiceImpl implements MyService {
public void do(){
//the transaction annotation won't work if you directly invoke handle() method with 'this'
this.handle();
}
@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public void handle() {
//sth with transaction
}
}
如果直接调用this的handle()方法则事务无法生效,原因是spring的AOP是通过代理实现的,像这样直接调用本对象的方法是不会应用代理的。
可以使用如下两种方式修改代码以应用事务
(1)在MyServiceImpl中声明一个MyService对象
public class MyServiceImpl implements MyService {
@Autowired
private MyService myService;
public void do(){
//use myService object
myService.handle();
}
@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public void handle() {
//sth. with transaction
}
}
(2)使用AopContext类
public class MyServiceImpl implements MyService {
public void do(){
//fetch current proxy objet from AopContext
((MyService)AopContext.currentProxy()).handle();
}
@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public void handle() {
//sth with transaction
}
}
注意,原生的AspectJ是不会有这种自身调用的问题的,因为它不是基于代理的AOP框架。
spring aop 内部方法调用事务不生效
方法1:
基于 proxy 的 spring aop 带来的内部调用问题可以使用 AopContext.currentProxy() 强转为当前的再调用就可以解决了
例如:
错误用法:
public Account getAccountByName2(String userName) {
return this.getAccountByName(userName);
}
修改为:
public Account getAccountByName2(String userName) {
return ((AccountService)AopContext.currentProxy()).getAccountByName(userName);
}
另外注意:要设置aop实体暴露出来。在springboot的application.java里面加上
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
方法2:
利用初始化方法在目标对象中注入代理对象
在目标对象类中注入spring上下文,通过context获取代理对象,并调用代理对象的方法。
注意:该方案对于scope为prototype的bean无法适用,因为每次获取bean时都返回一个新的对象。
方法2.1:
//延迟加载方式
private TestService testService;
@Autowired
@Lazy
public void setTestService(TestService testService) {
this.testService = testService;
}
方法2.2:
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import com.blog.common.aop.service.TestService;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private ApplicationContext context;
private TestService proxyObject;
@PostConstruct
// 初始化方法,在IOC注入完成后会执行该方法
private void setSelf() {
// 从spring上下文获取代理对象(直接通过proxyObject=this是不对的,this是目标对象)
// 此种方法不适合于prototype Bean,因为每次getBean返回一个新的Bean
proxyObject = context.getBean(TestService.class);
}
public void methodA() throws Exception {
System.out.println("method A run");
System.out.println("method A 中调用method B,通过注入的代理对象,调用代理对象的方法,解决内部调用实现的问题。");
proxyObject.methodB(); //调用代理对象的方法,解决内部调用失效的问题
}
public void methodB() {
System.out.println("method B run");
}
}
上一篇:mybatis中注解与xml配置的对应关系和对比分析
栏 目:JAVA代码
下一篇:JAVA自定义注解详情
本文标题:解决spring AOP中自身方法调用无法应用代理的问题
本文地址:http://www.codeinn.net/misctech/192006.html


阅读排行
- 1Java Swing组件BoxLayout布局用法示例
- 2java中-jar 与nohup的对比
- 3Java邮件发送程序(可以同时发给多个地址、可以带附件)
- 4Caused by: java.lang.ClassNotFoundException: org.objectweb.asm.Type异常
- 5Java中自定义异常详解及实例代码
- 6深入理解Java中的克隆
- 7java读取excel文件的两种方法
- 8解析SpringSecurity+JWT认证流程实现
- 9spring boot里增加表单验证hibernate-validator并在freemarker模板里显示错误信息(推荐)
- 10深入解析java虚拟机




