学好spring,走遍天下都是win

Spring 动态代理不生效问题

2020-12-03  本文已影响0人  藤原咸鱼

1.静态代理,动态代理

静态代理:代理类和代理目标存在硬编码关系,耦合度高
动态代理:代理类通过java反射,在jvm运行时动态生成,实现代码解耦

2.JDK动态代理,cglib动态代理

JDK动态代理:通过反射类Proxy以及InvocationHandler回调接口实现的,被代理类必须实现自接口
cglib动态代理:通过ASM(字节码技术)框架生成代理类,被代理对象为public且不为final修饰,因为cglib原理是动态生成被代理类的子类

接口(Subject):
interface HelloService {
    void sayHello();
}

委托类:
class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        System.out.println("Hello World!");
    }
}

JDK代理核心代码,构造代理对象
class HelloServiceDynamicProxy {

    private HelloService helloService;
    public HelloServiceDynamicProxy(HelloService helloService) {
        this.helloService = helloService;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(helloService.getClass().getClassLoader(), helloService.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("Before say hello...");
                Object ret = method.invoke(helloService, args);
                System.out.println("After say hello...");
                return ret;
            }
        });
    }
}
 }

测试类:
public class HelloServieDynamicProxyTest {
    public static void main(String[] args){
        HelloService helloService = new HelloServiceImpl();
        HelloService dynamicProxy = (HelloService) new HelloServiceDynamicProxy(helloService).getProxyInstance();
        dynamicProxy.sayHello();
    }
}

输出结果:
Before say hello...
Hello World!
After say hello...

了解过动态代理实现后,我们知道不管何种代理,作用对象是类,通过生成代理类,调用其方法。

结论:
Spring AOP 则是基于动态代理底层实现,对目标类的方法调用植入增强功能代码

所以基于aop的注解(例:@Transactional)具有共性特征自调用失效

(调用类中第一个方法没有注解,那么该方法这种调用本类中的其他注解方法都不起作用)

粗暴的解决方法
// 在A方法内部调用B方法
// 1.直接调用B,注解失效。
// 2.拿到代理类对象,再调用B(X类的B方法)。
((X)AopContext.currentProxy()).B()

上一篇下一篇

猜你喜欢

热点阅读