美文网首页JavaJava
Java中的静态代理和动态代理

Java中的静态代理和动态代理

作者: zhong0316 | 来源:发表于2019-02-21 18:24 被阅读1次

    什么是代理

    代理是设计模式的一种,代理类为委托类提供消息预处理,消息转发,事后消息处理等功能。Java中的代理分为三种角色:

    1. 代理类(ProxySubject)
    2. 委托类(RealSubject)
    3. 接口(Subject)

    三者关系可以表示如下图:

    代理模式

    Java中的代理按照代理类生成时机不同又分为静态代理和动态代理。静态代理代理类在编译期就生成,而动态代理代理类则是在Java运行时动态生成。

    静态代理

    Java中的静态代理要求代理类(ProxySubject)和委托类(RealSubject)都实现同一个接口(Subject)。静态代理中代理类在编译期就已经确定,而动态代理则是JVM运行时动态生成,静态代理的效率相对动态代理来说相对高一些,但是静态代理代码冗余大,一单需要修改接口,代理类和委托类都需要修改。
    举个例子:

    接口(Subject)

    interface HelloService {
        void sayHello();
    }
    

    委托类

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

    代理类

    class HelloServiceProxy implements HelloService {
        private HelloService helloService;
        
        public HelloServiceProxy(HelloService helloService) {
            this.helloService = helloService;
        }
        
        @Override
        public void sayHello() {
            System.out.println("Before say hello...");
            helloService.sayHello();
            System.out.println("After say hello...");
        }
    }
    

    测试类

    public class HelloServiceProxyTest {
        
        public static void main(String[] args) {
            HelloService helloService = new HelloServiceImpl();
            HelloServiceProxy proxy = new HelloServiceProxy(helloService);
            proxy.sayHello();
        }
    }
    

    输出结果

    Before say hello...
    Hello World!
    After say hello...
    

    动态代理

    Java中的动态代理依靠反射来实现,代理类和委托类不需要实现同一个接口。委托类需要实现接口,否则无法创建动态代理。代理类在JVM运行时动态生成,而不是编译期就能确定。
    Java动态代理主要涉及到两个类:java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler。代理类需要实现InvocationHandler接口或者创建匿名内部类,而Proxy用于创建动态动态。
    我们用动态代理来实现HelloService:

    接口(Subject)

    interface HelloService {
        void sayHello();
    }
    

    委托类

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

    动态代理类

    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...
    

    总结

    1. 静态代理实现较简单,代理类在编译期生成,效率高。缺点是会生成大量的代理类。
    2. JDK动态代理不要求代理类和委托类实现同一个接口,但是委托类需要实现接口,代理类需要实现InvocationHandler接口。
    3. 动态代理要求代理类InvocationHandler接口,通过反射代理方法,比较消耗系统性能,但可以减少代理类的数量,使用更灵活。

    相关文章

      网友评论

        本文标题:Java中的静态代理和动态代理

        本文链接:https://www.haomeiwen.com/subject/riudyqtx.html