【AOP问题处理】:AopContext.currentProxy()方法异常处理:java.lang.IllegalStateException: Cannot find current proxy: Set ‘exposeProxy’ property on Advised to ‘true’ to make it available.

原因是代理对象内部方法的调用不会触发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代理成功

© 版权声明
THE END
支持一下吧
点赞8 分享
评论 抢沙发
头像
请文明发言!
提交
头像

昵称

取消
昵称表情代码快捷回复

    暂无评论内容