Spring AOP实现原理--动态代理

Spring AOP底层是通过动态代理来实现的,其中包括JDK动态代理和cglib动态代理。

JDK动态代理

手写JDK动态代理

public interface UserInterface {
    Integer test();
}

被代理类

public class User implements UserInterface {

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private String name;

    @Override
    public Integer test() {
        return Integer.valueOf(name);
    }
}

代理类

public class JDKProxy implements InvocationHandler {

    private Object target;

    public JDKProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("-----before-----" + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("-----after-----" + result);
        return result;
    }
}

测试类

public class ProxyTest {
    public static void main(String[] args) {
        User user = new User();
        user.setName("123");
        UserInterface proxyInstance = (UserInterface) Proxy.newProxyInstance(User.class.getClassLoader(), User.class.getInterfaces(), new JDKProxy(user));
        proxyInstance.test();
    }
}

输出结果为:

-----before-----test

123

-----after-----123

还可能通过匿名内部类来实现,如下

public static void main(String[] args) {
    User user = new User();
    user.setName("123");
    UserInterface proxyInstance = (UserInterface) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("----before----" + method.getName());
            Object result = method.invoke(user, args);
            System.out.println("----after----" + result);
            return result;
        }
    });
    proxyInstance.test();
}

输出结果同上:

----before----test

123

----after----123

cglib动态代理

手写cglib动态代理

被代理类

public class User {
    void test() {
        System.out.println("test");
    }
}

代理类

public class UserCglibProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("---before---" + method.getName());
        Object result = methodProxy.invokeSuper(o, args);
        System.out.println("---after---" + result);
        return result;
    }
}

测试类

public class CglibTest {
    public static void main(String[] args) {
        UserCglibProxy cglibProxy = new UserCglibProxy();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(User.class);
        enhancer.setCallback(cglibProxy);
        User userTest = (User) enhancer.create();
        userTest.test();
    }
}

输出结果为:

---before---test

test

---after---null

JDK动态代理和cglib动态代理的区别

写法不同

根据以上代码,可以看出:

JDK动态代理需要实现InvocationHandler接口重写invoke方法。

cglib动态代理需要实现MethodInterceptor接口重写intercept方法,并通过Enhancer设置被代理类与代理类。

实现原理不同

JDK动态代理是利用拦截器(拦截器必须实现InvocationHandler)加上反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvocationHandler来实现的,所以Jdk动态代理必须是基于接口进行动态代理,并且成生的动态代理类实现了该接口。

cglib动态代理是利用ASM技术,加载代理类class文件并修改字节码生成子类来实现的,所以无法动态代理final修饰的方法。

效率不同

随着JDK版本升级,JDK动态代理一直在优化。在JDK1.6之前JDK动态代理效率低于cglib动态代理。JDK在1.6和1.7版本JDK动态代理效率高于cglib动态代理,只有当进行大量调用的时候,才会比cglib动态代理效率低一点。JDK1.8及之后JDK动态代理效率高于cglib动态代理。

JDK自带

JDK动态代理功能是JDK自带的,不需要任何依赖。

cglib动态代理功能不是JDK自带的需要引用相关依赖。

SpringAop用哪个?

默认用的是JDK动态代理,当未实现接口时用cglib动态代理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值