1 问题出现
//t1 调用t3 方法
public void t1(String name){
System.out.println("t1你好!"+name);
// 调用方法t3
t3(name);
}
public void t3(String name){
System.out.println("t3你好!"+name);
}
拦截器
// 拦截t1
@Before("e2()")
public void a5(JoinPoint joinPoint){
System.out.println("拦截了方法t1:"+ joinPoint.getSignature());
}
// 拦截t3
@Before("e6()")
public void a6(JoinPoint joinPoint){
System.out.println("拦截了方法t3:"+ joinPoint.getSignature());
}
方法调用与结果
TestDemo t2= (TestDemo) cpa.getBean("testDemo");
t2.t1("海绵宝宝");
/*
结果如下:
拦截了方法t1:void org.example.Day7.TestDemo.t1(String)
t1你好!海绵宝宝
t3你好!海绵宝宝
*/
发现并没有拦截t3
2 原因分析
这是由于spring aop实现的机制造成的,spring aop采用代理模式实现aop,将横切逻辑加到动态生成的代理对象中,只是调用的是目标对象的代理对象上的方法。当我们调用代理对象时(spring aop 自动代理),目标对象的方法就会被拦截。
如果目标对象方法调用依赖于其他对象,我们可以为其注入所依赖对象的代理,但是一旦目标对象依赖于自身所定义的其他方法时
在代理对象方法经过拦截器之后,最终会调用目标对象的t1,当t1 调用t3 时,走的是目标对象的t3,而不是代理对象的t3.
3 解决方案
当目标对象依赖于自身时,我们可以将其给公开。
让目标对象调用自身代理对象上的相应方法。可以通过AopContext.currentProxy()
方法取得目前对象对应的代理对象
public void t1(String name){
System.out.println("t1你好!"+name);
//调用本身代理对象的t3 方法
((TestDemo)AopContext.currentProxy()).t3(name);
}
public void t3(String name) {
System.out.println("t3你好!"+name);
}
要让其生效需要配置exposeProxy属性
<aop:aspectj-autoproxy expose-proxy="true"/>
结果
拦截了方法t1:void org.example.Day7.TestDemo.t1(String)
t1你好!海绵宝宝
调用方法3
拦截了方法t3:void org.example.Day7.TestDemo.t3(String)
t3你好!海绵宝宝