zoukankan      html  css  js  c++  java
  • Java动态代理(举例)

         通过JDK实现动态代理,有代理需求的类(这里称之为实现类)必须要实现接口。动态代理可以将逻辑切片,通过代理类(proxy)代实现类实现逻辑,期间还可以进行一些其他的操作。JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中 InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,在并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一 起。关于动态这块儿一直比较迷惑,傻傻分不清楚,今天又有了新的理解,下面通过一个简单的例子来说明:

       先叙述下事务逻辑:一个人(people对象)通过交通工具(Transportation处理类)去了外国(日本、英国)

      1、将去英国和日本这两件事当做两个接口,由人来实现

       

    package com.impetention.lei;
    
    public interface Japan
    {
       public void goJapan();
    }
    --------------------------------------------
    package com.impetention.lei;
    
    public interface England
    {
        public void goEngland();
    }
    -------------------------------------------------
    package com.impetention.lei;
    //实现类
    public class People implements England,Japan
    {
        @Override
        public void goEngland()
        {
            // TODO Auto-generated method stub
            System.out.println("I am in England !");
        }
    
        @Override
        public void goJapan()
        {
            // TODO Auto-generated method stub
            System.out.println("I am in Japan !");
        }
    
    }

    2、现在介绍一下InvocationHandler ,它是代理类的调用处理程序 实现的接口。每个代理类都具有一个关联的调用处理程序,在实例化代理类时会添加进去一个InvocationHandler类型的处理类(完成事务逻辑的主题)。

    如:

    package com.invocation;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    import com.impetention.lei.People;
    
    //人通过交通工具(代理)去国外
    public class Transportation implements InvocationHandler
    {
        //一个叫zhang的人
        private Object zhang = null;
        
        public Transportation(Object zhang)
        {
            this.zhang = zhang;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) 
        {
            // TODO Auto-generated method stub
            System.out.println("可以执行一些其他方法.....");
            //记录执行结果
            Object result = null;
            zhang = new People();
            //在zhang对象上执行method方法,并将结果返回
            try
            {
                result = method.invoke(zhang, args);
            } catch (Exception e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("---------------------");
            return result;
        }
    
    }

    注意里面红色的proxy,它就是代理类实例。这里有必要对invoke(Object proxy, Method method, Object[] args) 做出一些解释,动态代理类proxy0调用goEngland()方法时会调用它自己的goEngland()方法, 而它自己的goEngland()方法里面调用的是其绑定对象InvocationHandler对象的invoke()方法, 也就是Transportation的invoke方法。invoke(Object proxy, Method m, Object[] args)种的proxy实际上就是动态代理类proxy, 如果你将其强转成England然后调用它的goEngland()方法,它又会触发代理类的goEngland()方法,代理类又调用InvocationHandler(transportation)的invoke()方法,这样就会死循环。

     3、代理实现:

    package com.main;
    
    import java.lang.reflect.Proxy;
    
    import com.impetention.lei.England;
    import com.impetention.lei.Japan;
    import com.impetention.lei.People;
    import com.invocation.Transportation;
    
    public class Peopletest
    {
        public static void main(String[] args)
        {
            //准备用动态代理实现,一个叫li的人通过交通工具到了英国
            England li = new People();
            //实例化transportation对象
            Transportation t1 = new Transportation(li);
            //通过li.getClass().getClassLoader()实现类的类加载器和li.getClass().getInterfaces()实现类实现的所有接口作为参数调用                 
    //Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces)的方法返回代理类的java.lang.Class对象获得了一个proxy代理类,
    //必须给它一个InvocationHandler参数,也就是我们自己实现的用来在代理类方法执行前后做额外工作的类transpotation。将代理类强转成England类型
    England proxy = (England) Proxy.newProxyInstance(li.getClass().getClassLoader(),
                    li.getClass().getInterfaces(), t1);
            proxy.goEngland();
            //准备用动态代理实现,一个叫li的人通过交通工具到了英国
                    Japan lei = new People();
                    //实例化transportation对象
                    Transportation t2 = new Transportation(lei);
                    //通过li.getClass().getClassLoader()和li.getClass().getInterfaces()获得了一个
                    //(java.lang.class)proxy代理类,并以tt为参数对其进行实例化,强转成people类型
                    Japan proxy1 = (Japan) Proxy.newProxyInstance(li.getClass().getClassLoader(),
                            li.getClass().getInterfaces(), t2);
                    proxy1.goJapan();
            
            
        }
    }
    小结:过程是这样的,people执行goEngland()方法不直接执行,而是通过代理类proxy,proxy执行它自己的goEngland(),会触发Transportation调用invoke(),然后
    method.invoke(zhang, args);zhang会调用它的method,即goEngland(),最后将结果返回。
  • 相关阅读:
    iOS面试题6.30总结
    关于外挂
    webstorm快捷方式
    HTML注释的一些规范
    认识Python
    正体复本术解决容易疲劳、不能持续集中精力工作-海淀区非物质文化遗产:#正体复本术#
    皮肤发痒的观察与思考
    win10不错的快捷键
    项目属性的target platform和target platform version到底是什么(vs2015开发windows驱动小记)
    玩Web虎-运行时受保护文件不可复制
  • 原文地址:https://www.cnblogs.com/90zyh/p/3099322.html
Copyright © 2011-2022 走看看