原因是代理对象内部方法的调用不会触发AOP代理。
先看代码:
自定义了一个注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 使用元注解来指定注解的使用场景和生命周期
@Target({ElementType.METHOD}) // 可以用于方法
@Retention(RetentionPolicy.RUNTIME) // 运行时保留,可以通过反射获取
public @interface Annotation1 {
// 定义一个名为value的注解属性
String value() default "";
}
以及一个切面类,添加了注解@Annotation1的方法会触发AOP代理:
@Aspect
public class TestAspect {
@Around(value = "@annotation(annotation1)")
public Object around(ProceedingJoinPoint joinPoint, Annotation1 annotation1) throws Throwable {
// 前置逻辑
//......
// 方法执行
Object resultObject = joinPoint.proceed();
// 后置逻辑
//......
// 如果不需要阻止,则执行目标方法
return resultObject;
}
}
添加了注解@Annotation1的方法,以及报错的代码段:
@Service
public class MyService {
public void someInternalMethod() {
// 获取当前代理对象
MyService proxy = (MyService) AopContext.currentProxy();
// 通过代理对象调用方法
proxy.method1();
}
@Annotation1
public void method1() {
// ...
}
}
本意是方法method1被调用时触发AOP代理,做一些逻辑处理,但是在Java中,默认情况下,方法内部的调用(即非通过代理的调用)是不会触发AOP(面向切面编程)代理的,所以选择使用this或AopContext.currentProxy()显式调用,这里使用的是AopContext.currentProxy(),如下:
/**
* Try to return the current AOP proxy. This method is usable only if the
* calling method has been invoked via AOP, and the AOP framework has been set
* to expose proxies. Otherwise, this method will throw an IllegalStateException.
* @return the current AOP proxy (never returns {@code null})
* @throws IllegalStateException if the proxy cannot be found, because the
* method was invoked outside an AOP invocation context, or because the
* AOP framework has not been configured to expose the proxy
*/
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;
}
看到这里的报错信息"Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available."就是未访问到当前线程的代理对象proxy,它提示我们将Advised对象(Advised对象:已经被Spring AOP代理包装的对象)的exposeProxy属性设置为true以使其可被访问。(exposeProxy属性表示是否暴露生成的代理类,暴露就是可手动调用)
所以只要将需要代理的对象类添加注解来设置属性exposeProxy = true
@EnableAspectJAutoProxy(exposeProxy = true)
即:
@EnableAspectJAutoProxy(exposeProxy = true)
@Service
public class MyService {
public void someInternalMethod() {
// 获取当前代理对象
MyService proxy = (MyService) AopContext.currentProxy();
// 通过代理对象调用方法
proxy.method1();
}
@Annotation1
public void method1() {
// ...
}
}
运行调用就可以成功获取MyService的代理对象,并且通过代理对象调用method1方法时,就会触发AOP代理成功
标签:lang,Set,exposeProxy,代理,current,proxy,AOP,true,public From: https://www.cnblogs.com/masterman/p/18258770