欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-09 19:00:09
摘要 之前老是听说动态代理,一直没有机会好好看过,现在就把动态代理的实现逻辑和用处整理一下。首先提两个概念,委托类和代理类。委托类就是实际业务逻辑的处理者,代理类是处于请求发起者与委托类之间的角色,所有对委托类的请求都会经过代理类。就是委托类将请求处理委托给代理类,代理类可以起到方法拦截、功能增强的 ......
  • 摘要
      之前老是听说动态代理,一直没有机会好好看过,现在就把动态代理的实现逻辑和用处整理一下。
    首先提两个概念,委托类和代理类。委托类就是实际业务逻辑的处理者,代理类是处于请求发起者与委托类之间的角色,所有对委托类的请求都会经过代理类。
    就是委托类将请求处理委托给代理类,代理类可以起到方法拦截、功能增强的作用。
    实现动态代理的方式有很多,现在主流的主要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