当前位置: 移动技术网 > IT编程>软件设计>设计模式 > 设计模式(一) 动态代理初尝试

设计模式(一) 动态代理初尝试

2019年02月27日  | 移动技术网IT编程  | 我要评论
  • 摘要
      之前老是听说动态代理,一直没有机会好好看过,现在就把动态代理的实现逻辑和用处整理一下。
    首先提两个概念,委托类和代理类。委托类就是实际业务逻辑的处理者,代理类是处于请求发起者与委托类之间的角色,所有对委托类的请求都会经过代理类。
    就是委托类将请求处理委托给代理类,代理类可以起到方法拦截、功能增强的作用。
    实现动态代理的方式有很多,现在主流的主要jdk和cglib这两个。下面就用示例代码说明下动态代理的过程,以及用动态代理实现拦截器。
  • 用jdk实现动态代理
      jdk实现动态代理的包是java.lang.reflect.*,jdk实现动态代理有限制,委托类必须要实现接口,所以先要创建一个接口
    public interface myinterface {
    
        //jdk
        public void tes1();
    
        //cglib
        public void test2(string val);
    
    }


    创建接口实现类

    public class mytarget implements myinterface {
    
        //jdk
        @override
        public void tes1() {
            system.out.println("委托类业务处理!");
        }
    
        //cglib
        @override
        public void test2(string val) {
            system.out.println("业务处理结果:"+val);
        }
    }


    动态代理逻辑代码

    package proxy;
    
    import java.lang.reflect.invocationhandler;
    import java.lang.reflect.method;
    import java.lang.reflect.proxy;
    
    public class myproxytest implements invocationhandler {  //继承invocationhandler,拦截方法
    
        private object target=null;
    
        //构造函数
        public myproxytest(object target){
            this.target = target ;
        }
    
        //获取代理类的方法
        public static object getproxy(object target){
            //通过proxy创建代理类,需要三个参数,委托类的类加载器、委托类实现的接口、代理类
            /**
             * 这是jdk的动态代理模式,必须要有接口
             * proxy会把代理类挂载到所有接口下面
             * 如果委托类没有实现任何接口会有问题,改用cglib的enhancer增强类做动态代理
             */
            return proxy.newproxyinstance(target.getclass().getclassloader(),
                    target.getclass().getinterfaces(),new myproxytest(target));
        }
    
        //拦截方法
        @override
        public object invoke(object proxy, method method, object[] args) throws throwable {
            system.out.println("进入代理逻辑!");
            system.out.println("代理类处理逻辑!");
            object result=null;
            result = method.invoke(target,args);
            system.out.println("委托类处理完后的逻辑!");
            return result;
        }
    }

      getproxy方法就是绑定委托类和代理类之间关系的方法,这里绑定的代理类是this当前对象,也就是myproxytest 的实例对象,由于实现了invocationhandler接口,所以在方法调用之前都会
    通过invoke方法,在这里就可以写功能增强的代码。method.invoke(target,args)是通过反射运行委托类的方法。

    测试用例

    public class junittest {
        public static void main(string[] args) {
            /**
             * jdk动态代理
             */
            system.out.println("---------jdk动态代理--------");
            //委托类
            mytarget target = new mytarget();
            //给委托类绑定代理类
            myinterface proxy = (myinterface)myproxytest.getproxy(target);
            proxy.tes1();
        }
    }


    运行结果

    ---------jdk动态代理--------
    进入代理逻辑!
    代理类处理逻辑!
    委托类业务处理!
    委托类处理完后的逻辑!

    我们发现进入了代理类的处理逻辑。



  • cglib实现动态代理
      cglib实现动态代理和jdk大同小异,不过cglib是通过创建增强类enhancer,并且设置enhancer的委托类和代理类来实现动态代理。cglib的委托类不需要实现接口。
    动态代理逻辑
    package proxy;
    
    import org.springframework.cglib.proxy.enhancer;
    import org.springframework.cglib.proxy.methodinterceptor;
    import org.springframework.cglib.proxy.methodproxy;
    
    import java.lang.reflect.method;
    
    public class mycglibproxy implements methodinterceptor {
    
        public object getproxy(class target){
            //创建增强类
            enhancer enhancer = new enhancer();
            //设置委托类
            enhancer.setsuperclass(target);
            //设置代理类
            enhancer.setcallback(this);
            return enhancer.create();
        }
    
    
        @override
        public object intercept(object o, method method, object[] objects, methodproxy methodproxy) throws throwable {
            system.out.println("进入代理逻辑!");
            system.out.println("代理类处理逻辑!");
            object result=null;
            result = methodproxy.invokesuper(o,objects);
            system.out.println("委托类处理完后的逻辑!");
            return result;
        }
    }

    这里的getproxy接收的不是委托类的实例对象而是委托类。代理类是this,mycglibproxy 的实例对象,由于实现了methodinterceptor拦截器,所以方法调用都会经过intercept。

    测试用例

    package proxy;
    
    public class junittest {
        public static void main(string[] args) {
            /**
             * cglib动态代理
             */
            system.out.println("---------cglib动态代理--------");
            mycglibproxy cglib = new mycglibproxy();
            myinterface cglibproxy = (myinterface)cglib.getproxy(mytarget.class);
            cglibproxy.test2("cglib动态代理");
        }
    }

    运行结果

    ---------cglib动态代理--------
    进入代理逻辑!
    代理类处理逻辑!
    业务处理结果:cglib动态代理
    委托类处理完后的逻辑!

    简单的实现动态代理的两种方式就完成了,之后再讲解拦截器和责任链模式

  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网