Java笔记(二十一) 动态代理

动态代理

一、静态代理

代理的背后一般至少有一个实际对象,代理的外部功能和实际对象一般是一样的,

用户与代理打交道,不直接接触实际对象。代理存在的价值:

1)节省成本比较高的实际对象创建开销,按需延迟加载,创建代理时

并不正真创建实际对象,而只是保存实际对象的地址,在需要时再加载或者创建。

2)执行权限检查,代理检查权限后再调用实际对象。

3)屏蔽网络的差异性和复杂性,代理在本地,而实际对象在其他服务器上,调用

本地代理时,本地代理请求其他服务器。

静态代理示例:

public class SimpleStaticProxy {
    //服务接口
    static interface IService {
        void sayHello();
    }
    //服务类
    static class RealService implements IService {
        @Override
        public void sayHello() {
            System.out.println("hi");
        }
    }
    //代理类
    static class TraceProxy implements IService {
        private IService realService;

        public TraceProxy(IService realService) {
            this.realService = realService;
        }

        @Override
        public void sayHello() {
            System.out.println("Start say hi");
            realService.sayHello();
            System.out.println("End say hi");
        }
    }

    public static void main(String[] args) {
        RealService service = new RealService();
        TraceProxy traceProxy = new TraceProxy(service);
        traceProxy.sayHello();
    }
}

静态代理缺陷:如果每个类都需要代理,我们需要为每个类都创建代理类,

实现所有接口,这个工作量相当大。

二、Java SDK代理

所谓动态代理,代理类是动态生成的。

1.用法

public class SimpleJDKDynamicProxy {
    interface IService {
        void sayHello();
        void sayGoodBye();
    }
    static class RealService implements IService {
        @Override
        public void sayHello() {
            System.out.println("hi");
        }
        @Override
        public void sayGoodBye() {
            System.out.println("GoodBye world!");
        }
    }
    static class SimpleInvocateHandler implements InvocationHandler {
        private Object realObj;
        public SimpleInvocateHandler(Object realObj) {
            this.realObj = realObj;
        }
        /**
        * @param proxy 表示代理对象本身,注意它不是被代理的对象,这个参数用处不大
        * @param method 表示正在被调用的方法
        * @param args 表示方法的参数
        * */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Start " + method.getName());
            Object result = method.invoke(realObj, args);
            System.out.println("End " + method.getName());
            return result;
        }
    }
    public static void main(String[] args) {
        IService realService = new RealService();
        IService proxyService = (IService) Proxy.newProxyInstance(IService.class.getClassLoader(),
                new Class<?>[]{IService.class}, new SimpleInvocateHandler(realService));
        proxyService.sayHello();
        proxyService.sayGoodBye();
    }
}
/**
    * @param loader 类加载器
    * @param interfaces 代理类要实现的接口列表
    * @param h 该接口定义了invoke方法,对代理接口所有的方法调用都会转给该方法
    * @return 可以转换为interfaces数组中的某个接口类型,注意只能转换为接口不能转换为具体的类
    * */
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces, InvocationHandler h);

2.基本原理

创建proxyService的代码可以用如下的代码代替:

//创建代理类定义,类定义会被缓存
Class<?> proxyCls = Proxy.getProxyClass(IService.class.getClassLoader(), new Class<?>[] { IService.class });
//获取代理类的构造方法
Constructor<?> ctor = proxyCls.getConstructor(new Class<?>[] { InvocationHandler.class });
InvocationHandler handler = new SimpleInvocationHandler(realService);
//创建代理类对象
IService proxyService = (IService) ctor.newInstance(handler);
    final class $Proxy0 extends Proxy implements SimpleJDKDynamicProxyDemo.IService {
        private static Method m1;
        private static Method m3;
        private static Method m2;
        private static Method m0;
        public $Proxy0(InvocationHandler paramInvocationHandler) {
            super(paramInvocationHandler);
        }
        public final boolean equals(Object paramObject) {
            return((Boolean) this.h.invoke(this, m1,
                    new Object[] { paramObject })).booleanValue();
        }
        public final void sayHello() {
            this.h.invoke(this, m3, null);
        }
        public final String toString() {
            return (String) this.h.invoke(this, m2, null);
        }
        public final int hashCode() {
            return ((Integer) this.h.invoke(this, m0, null)).intValue();
        }
        static {
            m1 = Class.forName("java.lang.Object").getMethod("equals",
                    new Class[] { Class.forName("java.lang.Object") });
            m3 = Class.forName(
                    "laoma.demo.proxy.SimpleJDKDynamicProxyDemo$IService")
                    .getMethod("sayHello",new Class[0]);
            m2 = Class.forName("java.lang.Object")
                    .getMethod("toString", new Class[0]);
            m0 = Class.forName("java.lang.Object")
                    .getMethod("hashCode", new Class[0]);
        }
    }

三、cglib动态代理

Java SDK动态代理的局限,它只能为接口创建代理,返回的代理对象也只能转换到某个接口类型。

public class SimpleCGLibDemo {
    static class RealService {
        public void sayHello() {
            System.out.println("hello");
        }
    }
    static class SimpleInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object object, Method method, Object[] args,
                                MethodProxy methodProxy) throws Throwable {
            System.out.println("start " + method.getName());
            Object result = methodProxy.invokeSuper(object, args);
            System.out.println("end " + method.getName());
            return result;
        }
    }
    private static <T> T getProxy(Class<T> cls) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(cls);
        enhancer.setCallback(new SimpleInterceptor());
        return (T) enhancer.create();
    }
    public static void main(String[] args) {
        RealService proxy = getProxy(RealService.class);
        proxy.sayHello();
    }
}

cglib是通过继承实现的,具体原理略。

原文地址:https://www.cnblogs.com/Shadowplay/p/10005222.html