如何通过AspectJ拦截MyAbstractObject子类中MyOtherObject的setter方法?
解决Spring AspectJ拦截抽象类返回对象setter的问题
你之前的切入点写法execution(* mypackage.MyAbstractObject.getMyOtherObject().set*(*))语法错误,因为execution切入点只能匹配单个方法的执行,不支持链式调用(比如.getMyOtherObject().set*这种写法),所以会抛出格式错误的异常。
下面提供两种可行方案,实现仅拦截继承自MyAbstractObject的类中getMyOtherObject()返回对象的setter方法:
方案一:使用原生AspectJ控制流切入点(需开启AspectJ织入)
如果项目可以启用原生AspectJ织入(编译时或加载时),可以通过控制流cflow()来匹配getMyOtherObject()调用后的setter操作:
@Aspect @Component public class MyAspects { @Before("call(* set*(..)) && cflow(execution(* mypackage.MyAbstractObject.getMyOtherObject()))") public void beforeSetterInGetMyOtherObjectFlow(JoinPoint joinPoint) { // 这里编写你的处理逻辑 System.out.println("拦截到MyAbstractObject子类返回对象的setter调用:" + joinPoint.getSignature().getName()); } }
说明
call(* set*(..)):匹配所有setter方法的调用cflow(execution(* mypackage.MyAbstractObject.getMyOtherObject())):限定当前setter调用处于getMyOtherObject()方法的执行流程内,确保仅拦截从MyAbstractObject子类获取的对象的setter
配置要求
Spring项目中需要开启AspectJ自动代理,在配置类添加:
@EnableAspectJAutoProxy(proxyTargetClass = true)
如果使用XML配置:
<aop:aspectj-autoproxy proxy-target-class="true"/>
若需加载时织入,还需额外配置aop.xml和JVM参数。
方案二:动态代理返回对象(兼容Spring AOP)
如果不想依赖原生AspectJ,可在拦截getMyOtherObject()方法时,对返回对象创建动态代理,拦截其setter:
JDK动态代理(适用于实现接口的对象)
@Aspect @Component public class MyAspects { @Around("execution(* mypackage.MyAbstractObject.getMyOtherObject())") public Object aroundGetMyOtherObject(ProceedingJoinPoint joinPoint) throws Throwable { Object originalObj = joinPoint.proceed(); if (originalObj == null) { return null; } // 创建JDK动态代理 return Proxy.newProxyInstance( originalObj.getClass().getClassLoader(), originalObj.getClass().getInterfaces(), (proxy, method, args) -> { // 拦截setter方法 if (method.getName().startsWith("set")) { // 执行前置逻辑 System.out.println("拦截到setter调用:" + method.getName()); } // 执行原方法 return method.invoke(originalObj, args); } ); } }
CGLIB代理(适用于未实现接口的对象)
如果返回对象没有实现接口,需引入CGLIB依赖,然后使用CGLIB创建代理:
@Aspect @Component public class MyAspects { @Around("execution(* mypackage.MyAbstractObject.getMyOtherObject())") public Object aroundGetMyOtherObject(ProceedingJoinPoint joinPoint) throws Throwable { Object originalObj = joinPoint.proceed(); if (originalObj == null) { return null; } // 创建CGLIB代理 Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(originalObj.getClass()); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { if (method.getName().startsWith("set")) { // 前置处理逻辑 System.out.println("拦截到setter调用:" + method.getName()); } return methodProxy.invokeSuper(proxy, args); } }); return enhancer.create(); } }
说明
这种方式直接在获取对象时生成代理,仅对从MyAbstractObject子类获取的对象生效,不会影响其他地方使用的同类型对象,完全兼容Spring AOP的代理机制。
内容的提问来源于stack exchange,提问作者maqjav
相关产品推荐
相关产品推荐

