动态代理


JDK动态代理

spring aop 默认使用的是JDK动态代理。如果一个类实现了一个接口,则spring则会用这种方式进行代理。
首先是实现InvocationHandler接口, 重写invoke方法, 这个方法就是代理的方法。其次是Proxy类,通过这个类的newProxyInstance方法, 返回一个代理对象。生成的代理对象实现原来那个类的所有接口, 并对接口的方法进行代理 , 通过代理对象调用这些方法,底层通过反射实现, 调用我们实现的invoke方法。

优点

原生, 不需要任何依赖。

通过反射机制生成的代理类的速度比CGLib操作字节码生成的代理类的速度更快。

缺点

被代理的类必须继承一个或多个接口,否则无法代理。

无法为没有在接口中定义的方法实现代理。

代理方法时, 需要通过反射机制进行回调, 此时执行效率比较低。

CGLib动态代理

直接操作字节码, 生成类的子类,重写类的方法完成代理。

优点

被代理的类不需要实现接口,代理类可以直接继承被代理的类。

被代理的类是原来那个类的子类,所以能够被子类重写的方法都可以进行代理。

代理效率高于JDK的动态代理。

缺点

无法代理Final类。

无法对final方法, private方法进行代理。

通过字节码生成代理类,其速度要低于JDK通过反射生成代理类的速度。

例子

定义接口:

public interface Star {

    void sing(String name);

    void dance(String name);
}

接口实现类

public class Ll implements Star {

    public final void info(){
        System.out.println("info");
    }

    @Override
    public void sing(String name) {
        System.out.println(name + " "+ "sing");
    }

    @Override
    public void dance(String name) {
        System.out.println(name + " "+ "dance");
    }
}

JDK动态代理:

public class StarProxy implements InvocationHandler {

    //目标类
    private Object object;

    public void setObject(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("earn money"); //增强
        method.invoke(object, args);
        return proxy;
    }

    //生成代理类
    public Object createProxyObject(){
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    }
}

cglib动态代理:

public class CglibProxy implements MethodInterceptor {

    //产生一个代理类
    public Object createProxyObject(Class clazz){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("earn money");
        return methodProxy.invokeSuper(o, objects);
    }
}

测试:

public class JdkProxyDemo {

    public static void main(String[] args) {
        Star star = new Ll();
        StarProxy starProxy = new StarProxy();
        starProxy.setObject(star);
        Object proxyObject = starProxy.createProxyObject();
        Star proxyStar = (Star)proxyObject;
        proxyStar.dance("aa");
    }
    //代理类不能直接包含被代理的对象, 而是一个InvocationHandler, InvocationHandler包含被代理的对象, 并负责分发请求给代理对象, 分发前后都可以做增强
}
public class CglibDemo {

    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        Ll star = (Ll) cglibProxy.createProxyObject(Ll.class);
        star.sing("bb");
        star.dance("cc");
        star.info();//因为info是final ,所以无法被代理
    }
}

文章作者:
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 !
评论
  目录