• Java动态代理-JDK自带实现


           上篇文章讲解了什么是静态代理,但是静态代理有一个问题就是需要建立很多的代理类,这样我们需要修改代理的方法的时候,需要在每个类中都要修改,这对于我们来说:当代理类很多的时候工作量就会成倍的增加。

           于是针对上述问题,人们就提出了解决方案,我们在运行中来实现代理类的创建,也就是今天要讲解的主题——动态代理,首先先说的是JDK自带的动态代理的实现。

             JDK自带的代理实现中最重要的两个内容:一是Proxy类,另一个是InvocationHandler接口。这两个是实现动态代理必须要用到的类和接口。

             1)对于InvocationHandler接口,API给出了这样的定义:           

         InvocationHandler 是代理实例的调用处理程序 实现的接口。

                    每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,

                    将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法

                   

             Object invoke(Object proxy,
                    Method method,
                    Object[] args)
                    throws Throwable

                       proxy:指代理的那个真实对象

                       method:指调用真是对象的某个方法Method对象

                       args:指调用真实对象某个方法时接受的参数

              2)Proxy类:

                    提供用于创建动态代理类和实例的静态方法,它还是由newProxyInstance方法创建的所有动态代理类的超类。

                   

             public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
                                   throws IllegalArgumentException

                   loader:定义代理类的类加载器

                   interface:代理类要实现的接口列表

                   h:指派方法调用处理程序

                   返回值:一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口

                                   也就是(返回一个由类加载器指定的代理类,它具有代理类Proxy中方法)这是我个人的理解

               以上已经对于JDK中用到的内容进行了简单的了解,接下来我们来看如何在代码中实现动态代理,


    1、定义一个接口

        

    public interface Hello {
        void say(String name);
    }


    2、定义一个类来实现这个接口,这个类就是我们的真实对象,HelloImpl

    public class HelloImpl implements Hello {
        @Override
        public void say(String name) {
    
            System.out.println("Hello!"+name);
        }
    
    
    }


    3、定义一个动态代理,每个动态代理类都必须实现InvocationHandler这个接口

    public class DynamicProxy implements InvocationHandler {
        private Object target;
    
        public DynamicProxy(Object target){
            this.target=target;
        }
    
        @SuppressWarnings("unchecked")
        public <T> T getProxy(){
            return (T) Proxy.newProxyInstance(
                    target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),
                    this
            );
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            before();
            Object result =method.invoke(target,args);
            after();
            return result;
        }
    
        private void before(){
            System.out.println("Before");
        }
    
        private void after(){
            System.out.println("After");
        }
    }
    


    4、接下来就是在客户端调用

    public class Test {
       
    
        public static void main(String[] args){
            Hello hello =new HelloImpl();
    
            DynamicProxy dynamicProxy = new DynamicProxy(hello);
    
            Hello helloProxy=(Hello) Proxy.newProxyInstance(
                    hello.getClass().getClassLoader(),
                    hello.getClass().getInterfaces(),
                    dynamicProxy
            );
            helloProxy.say("Jack");
            
    
        }
    }


    问题:由于上述在客户端调用过程中,每次动态创建代理类都会使用newProxyInstance这个方法,我们对其进行一层封装,如下:

    1、封装一个类,HelloProxy

    public class HelloProxy implements Hello {
        private  Hello hello;
    
        public HelloProxy(){
            hello=new HelloImpl();
        }
    
        @Override
        public void say(String name) {
            before();
            hello.say(name);
            after();
        }
    
        private void before(){
            System.out.println("Before");
        }
    
        private void after(){
            System.out.println("After");
        }
    }
    


    2、客户端调用


    public class Test {
       
        public static void main(String[] args){
            
            DynamicProxy dynamicProxy=new DynamicProxy(new HelloImpl());
            Hello helloProxy =dynamicProxy.getProxy();
            helloProxy.say("Jack");        
    
        }
    }
    


















  • 相关阅读:
    数据结构-线性表-链表
    [poj 2991]Crane[线段树表示向量之和,而非数量]
    vector要注意的点
    vector与deque的区别
    sendfile复习
    GPU和CPU的区别
    常用Linux命令 mount df dd
    可省略的关键字
    父类与子类的virtual
    加快编译的技巧 & mount及tmpfs
  • 原文地址:https://www.cnblogs.com/zsswpb/p/6329423.html
Copyright © 2020-2023  润新知