关于AOP无法切入同类调用方法的问题
2016-03-14 08:53
369 查看
总结:aop切面切入对于spring容器管理的类、方法 才有效,自己new的,或者同类方法调用的都无法切入
synchronized (this) {
System.out.println("--------------tradeAccountDao.save(a)==");
}
if(1==1){
throw new StaleObjectStateException(null, null);
}
return null;
}
上面 update1()方法无法被切入
解决方案:手动注入service bean
参考:Spring在代码中获取bean的几种方式 /article/11400255.html
参考:
http://blog.csdn.net/z69183787/article/details/45622821 http://www.dexcoder.com/selfly/article/326
最近在开发中遇到一个问题,当在Service中定义了一个方法并且切入之后,从Controller里面调用该方法可以实现切入,但是当在同一个Service中实现另一方法并调用改方法时却无法切入。代码类似于:
[java] view
plain copy
/**
* Controller 你懂的
*/
public class Ctrl {
public void ctrl() {
......
service.callMethodA();
......
}
}
/**
* 业务实现
*/
public class Service {
/**
* 被Controller调用的方法
* 这个方法调用被切的方法
*/
public void callMethodA() {
......
callMethodB();
......
}
/**
* Aop切入的方法
*/
public void callMethodB() {
......
}
}
/**
* AOP的实现
*/
public class Aspect {
@@AfterReturning("execution(* Service.callMethodB(..))")
public void after() {
Logger.info("after call and do something.");
}
}
总之这样的调用根本不会进去切面,找了很久资料都不知道怎么回事,果然我还是太弱了。后来有幸得问高人,指点说Service中如此调用并非调用的是代理类中的方法,是不会被切进去的。换言之,必须要调用代理类才会被切进去。 那么应该怎么破呢?既然只有调用代理类的方法才能切入,那我们拿到代理类不就好了嘛。尝试性的在IDE里面搜Aop相关的类,一眼就看到一个叫AopContext的东西,看来游戏啊,里面有一个方法叫做currentProxy(),返回一个Object。怎么样都要试一下,果断的把这个object打印出来。报错了……
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/30/ef4560d5cfbd735df68184a445e2d88b.gif)
[java] view
plain copy
java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
等等,这个错有点眼熟,之前傻傻找不到问题的时候看过Spring的配置。
[xml] view
plain copy
<aop:aspectj-autoproxy proxy-target-class="true"expose-proxy="true"/>
把expose-proxy设成true,再跑一次,终于没有报错了,而且打印出了令人欣喜的结果,currentProxy()的结果就是当前Service的代理类,那么事情简单了。修改Service的callMethodA()方法如下:
[java] view
plain copy
((Service) AopContext.currentProxy()).callMethodB();
成功了,方法成功的切入进去了,等下只要再把获取代理类的方法独立处理就好了。等等,突然脑洞大开,既然这样可以,那是不是直接applicationContext.getBean()也可以呢?实验过后得到的结果是可行,而且配置中的expose-proxy也不用设置成true。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/30/658903af0dc51685e805b6e177070698.gif)
总算这个问题算是解决了,但是以后在方法调用的时候就需要谨慎了,感觉应该有更好的办法解决这个问题,不知道哪位有更好的办法,能不能告诉我一下下呢?
<span style="white-space:pre"> </span>@Override public YbtTradeAccount update2() { System.out.println("===========我是第一步========="); this.update1(); return null; }
<span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public YbtTradeAccount update1() { <span style="white-space:pre"> </span><pre name="code" class="java"><span style="white-space:pre"> </span>System.out.println("===========我是第二步=========");
synchronized (this) {
System.out.println("--------------tradeAccountDao.save(a)==");
}
if(1==1){
throw new StaleObjectStateException(null, null);
}
return null;
}
上面 update1()方法无法被切入
解决方案:手动注入service bean
参考:Spring在代码中获取bean的几种方式 /article/11400255.html
参考:
http://blog.csdn.net/z69183787/article/details/45622821 http://www.dexcoder.com/selfly/article/326
最近在开发中遇到一个问题,当在Service中定义了一个方法并且切入之后,从Controller里面调用该方法可以实现切入,但是当在同一个Service中实现另一方法并调用改方法时却无法切入。代码类似于:
[java] view
plain copy
/**
* Controller 你懂的
*/
public class Ctrl {
public void ctrl() {
......
service.callMethodA();
......
}
}
/**
* 业务实现
*/
public class Service {
/**
* 被Controller调用的方法
* 这个方法调用被切的方法
*/
public void callMethodA() {
......
callMethodB();
......
}
/**
* Aop切入的方法
*/
public void callMethodB() {
......
}
}
/**
* AOP的实现
*/
public class Aspect {
@@AfterReturning("execution(* Service.callMethodB(..))")
public void after() {
Logger.info("after call and do something.");
}
}
总之这样的调用根本不会进去切面,找了很久资料都不知道怎么回事,果然我还是太弱了。后来有幸得问高人,指点说Service中如此调用并非调用的是代理类中的方法,是不会被切进去的。换言之,必须要调用代理类才会被切进去。 那么应该怎么破呢?既然只有调用代理类的方法才能切入,那我们拿到代理类不就好了嘛。尝试性的在IDE里面搜Aop相关的类,一眼就看到一个叫AopContext的东西,看来游戏啊,里面有一个方法叫做currentProxy(),返回一个Object。怎么样都要试一下,果断的把这个object打印出来。报错了……
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/30/ef4560d5cfbd735df68184a445e2d88b.gif)
[java] view
plain copy
java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
等等,这个错有点眼熟,之前傻傻找不到问题的时候看过Spring的配置。
[xml] view
plain copy
<aop:aspectj-autoproxy proxy-target-class="true"expose-proxy="true"/>
把expose-proxy设成true,再跑一次,终于没有报错了,而且打印出了令人欣喜的结果,currentProxy()的结果就是当前Service的代理类,那么事情简单了。修改Service的callMethodA()方法如下:
[java] view
plain copy
((Service) AopContext.currentProxy()).callMethodB();
成功了,方法成功的切入进去了,等下只要再把获取代理类的方法独立处理就好了。等等,突然脑洞大开,既然这样可以,那是不是直接applicationContext.getBean()也可以呢?实验过后得到的结果是可行,而且配置中的expose-proxy也不用设置成true。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/30/658903af0dc51685e805b6e177070698.gif)
总算这个问题算是解决了,但是以后在方法调用的时候就需要谨慎了,感觉应该有更好的办法解决这个问题,不知道哪位有更好的办法,能不能告诉我一下下呢?
相关文章推荐
- Android系统架构
- GemFire 8.2 在CentOS的安装步骤
- 每天进步一点点——Linux中的线程局部存储(二)
- GIS+=地理信息+容器技术(5)——Docker的网络设置和存储挂载
- I.MX6 Linux kernel LVDS backlight enable
- Linux中使用SecureCRT上传、下载文件命令sz与rz用法实例
- Linux 内核消息两则: 4.5 发布,历史最悠久的 LTS 内核 2.6.32 终止支持
- 【J2EE】:MVC是框架?是设计模式?是架构?还是……
- Mozilla 在 Firefox 46.0 中再次拿 GTK3 集成来挑逗 Linux 用户们
- 大流量网站性能优化:一步一步打造一个适合自己的BigRender插件
- centos 6.x 编译安装subversion
- KVM 存储虚拟化 - 每天5分钟玩转 OpenStack(7)
- KVM 存储虚拟化 - 每天5分钟玩转 OpenStack(7)
- Git Bash怎么把本地的一个文件传送到github的操作方法
- linux下git自动补全命令
- atitit.木马病毒webshell的原理and设计 java c# .net php.
- atitit.木马病毒webshell的原理and设计 java c# .net php.
- atitit.木马病毒webshell的原理and设计 java c# .net php.
- 同步IO和异步IO
- Linux学习笔记2016.03.13