You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 04:55:23