SpringAOP调用同类方法不代理的问题

文章讨论了SpringAOP中Cglib代理模式的工作原理,指出执行方法的对象是代理的目标对象,而非代理类对象。并通过示例说明了在不直接使用目标对象调用方法时,代理机制如何介入并执行增强逻辑。
摘要由CSDN通过智能技术生成

记录下这个事情。

在我的设想中,同类方法的调用也可以走代理,毕竟都是一个类了,xxx()调用肯定走的是代理的方法,调试后发现跟我想的不一样,所以看了一下源码发现了这个事情。
结论是:Spring AOP最终执行的方法的对象是代理的目标对象,而不是生成的代理类对象

下面是Spring的CglibAopProxy源码:

 @Override
 protected Object invokeJoinpoint() throws Throwable {
 	if (this.methodProxy != null) {
 		return this.methodProxy.invoke(this.target, this.arguments);
	}
	else {
		return super.invokeJoinpoint();
	}
 }

如果你使用断点访问,很直观的就能看到,这个是你代理的目标对象。

再来看看Cglib的MethodInterceptorintercept方法

/**
 *
 * @param obj 表示要进行增强的对象
 * @param method 表示拦截的方法
 * @param args 参数数组
 * @param methodProxy 表示对方法的代理,规避反射调用
 * @return 执行结果
 * @throws Throwable 异常
 */
 @Override
 public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable

intercept方法中,obj是代理后的对象,不是你的目标对象,所以Spring在构建MethodInterceptor对象时把目标对象保存,然后在处理完成所有的增强后使用目标对象调用方法。

假设你不使用目标对象调用方法,调用同类方法会走代理实现,看下方的代码和具体的结果

public class TestCglib {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserDao.class);
        enhancer.setCallback(new LogInterceptor());
        UserDao userDao = (UserDao) enhancer.create();
        userDao.m1();
    }

    public static class UserDao {
        public void m1(){
            this.m2();
        }
        protected void m2(){}
    }
    public static class LogInterceptor implements MethodInterceptor {

        @Override
        public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            String methodName = method.getName();
            System.out.println("调用方法" + methodName +"之【前】的日志处理");
            Object result = methodProxy.invokeSuper(obj, objects);
            System.out.println("调用方法" + methodName +"之【后】的日志处理");
            return result;
        }

    }
}

结果:

调用方法m1之【前】的日志处理
调用方法m2之【前】的日志处理
调用方法m2之【后】的日志处理
调用方法m1之【后】的日志处理

总结

我的想法是没问题的,但在Spring中有特定的规则?我不确定是不是Spring做这样的处理是为了防止递归调用还是其他原因。最终我在本类中获取本类的bean,然后用这个bean调用方法

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值