zoukankan      html  css  js  c++  java
  • java之代理模式

    静态代理:

     java代理是一种模式--代理模式。采用代理模式,可以在不改变目标类代码的基础上,通过代理对象,来增加额外的功能(比如增加日志检测等)或者只需要目标对象的部分行为。

    java中,代理分为静态代理和动态代理。

    静态代理:我的理解是程序员自己或者用某些工具去自己创建或者生成代理类。在使用之前,代理类已经存在。

    动态代理:区别于静态代理,它是动态的,不需要程序员去自己创建,只需要采用现成的动态代理类库(jdk动态代理,cglib)调用某些类的某些方法,动态生成代理类。代理类在使用之前是不存在的。什么时候使用,什么时候创建。是动态的。

    静态代理:

    静态代理有两种实现方式。

    1.合成

    即将目标类作为代理类的全局成员。需要目标类实现接口

    接口:

    package com.wtd.staticproxy;
    
    public interface Moveable {
        void move();
    }

    目标类:

    package com.wtd.staticproxy;
    
    import java.util.Random;
    
    /**
     * @desc Car:被代理对象,真实对象
     * */
    public class Car implements Moveable {
    
        @Override
        public void move() {
            try {
                System.out.println("the car is running");
                Thread.sleep(new Random().nextInt(1000));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }

    代理类:

    package com.wtd.staticproxy;
    
    /**
     * @desc 静态代理 第二种方式:合成。
     * 静态代理,说白了,就是手动创建 代理类。手动创建的两种方式[继承,合成]
     * */
    public class Car2 implements Moveable {//代理类:必须和被代理类都实现统一的接口
        Car car;//被代理类类 (真实类)
        public Car2(Car car) {
            super();
            this.car= car;
        }
        @Override
        public void move() {
            System.out.println("the car start");//业余方法
            long startTime= System.currentTimeMillis();//业余方法
            car.move();//调用被代理类的功能方法
            long endTime= System.currentTimeMillis();//业余方法
            System.out.println("the car stop,use time:"+ (endTime-startTime)+"ms");//业余方法
        }
    
    }

    测试类:

    package com.wtd.staticproxy;
    
    public class Test {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Car car = new Car();//创建被代理类(真实类)
            Moveable m2= new Car2(car);//创建代理类
            m2.move();
        }
    
    }

    output:

    the car start
    the car is running
    the car stop,use time:681ms

    2.继承

    代理类继承目标类。不需要目标类继承接口。但是目标类必须不能被final修饰

    目标类:

    package com.wtd.staticproxy;
    
    import java.util.Random;
    
    /**
     * @desc Car:被代理对象,真实对象
     * */
    public class Car {
    
        public void move() {
            try {
                System.out.println("the car is running");
                Thread.sleep(new Random().nextInt(1000));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }

    代理类:

    package com.wtd.staticproxy;
    
    /**
     * @desc 静态代理有两种方式, 这是第一种:继承的方式、
     * 第二种:合成
     * */
    public class Car1 extends Car{
        @Override
        public void move() {
            System.out.println("汽车开始行驶");//业余方法
            long startTime= System.currentTimeMillis();//业余方法
            super.move();//调用父类的功能方法
            long endTime= System.currentTimeMillis();//业余方法
            System.out.println("汽车行驶结束,行驶了:"+ (endTime- startTime)+"毫秒");//业余方法
        }
    }

    测试类:

    package com.wtd.staticproxy;
    
    public class Test {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Car m= new Car1();
            m.move();
        }
    
    }

    output:

    the car start
    the car is running
    the car stop,use time:361ms

    动态代理:

    原理:类似于静态代理中的合成。被代理对象必须继承某一接口

    接口:

    package com.wtd.dynamicproxy3;
    
    public interface Moveable {
        void move();
        void run(String args);
    }

    目标对象(被代理对象):

    package com.wtd.dynamicproxy3;
    
    public class Car implements Moveable {
    
        @Override
        public void move() {
            System.out.println("Car move()");
        }
    
        @Override
        public void run(String args) {
            System.out.println("Car run()"+ args);
        }
    
    }

    调用处理器对象:InvocationHandler对象

    package com.wtd.dynamicproxy3;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class LogHandler implements InvocationHandler {
        private Object proxied;
        public LogHandler(Object proxied) {
            this.proxied= proxied;
            // TODO Auto-generated constructor stub
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            System.out.println(
                "----------proxy: "
                + proxy.getClass()
                + ", method: "
                + method+ ", args: "
                + args+ ", proxied: "
                + proxied.getClass());
    
            return method.invoke(proxied, args);
        }
    
    }

    测试类:

    package com.wtd.dynamicproxy3;
    
    import java.lang.reflect.Proxy;
    
    
    public class TestDynamicProxy {
        public static void main(String[] args) {
            Car car= new Car();
            Moveable m= (Moveable) Proxy.newProxyInstance(Moveable.class.getClassLoader(), 
                    new Class<?>[]{Moveable.class},
                    new LogHandler(car));
            m.move();
            m.run("haha");
        }
    }

    output:

    ----------proxy: class com.sun.proxy.$Proxy0, method: public abstract void com.wtd.dynamicproxy3.Moveable.move(), args: null, proxied: class com.wtd.dynamicproxy3.Car
    Car move()
    ----------proxy: class com.sun.proxy.$Proxy0, method: public abstract void com.wtd.dynamicproxy3.Moveable.run(java.lang.String), args: [Ljava.lang.Object;@5e743399, proxied: class com.wtd.dynamicproxy3.Car
    Car run()haha

    cglib动态代理:

    原理:类似于静态代理中的继承方式。被代理对象的类不能被final所修饰

    首先需要导入jar包:cglib-nodep-x.x.x.jar。可在mvnrepository下载。

    被代理类:父类:realObject:

    package com.wtd.cglibproxy;
    
    /**
     * 目标类;父类;被代理类
     * 不能被final所修饰
     * */
    public class Car {
        public void move() {
            System.out.println("the car running");
        }
    }

    方法拦截器类:

    package com.wtd.cglibproxy;
    
    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class CglibProxy implements MethodInterceptor {
        private Enhancer enhancer = new Enhancer();
        
        /**
         * 设置获得代理对象(即子类对象)的方法
         * 需要用到 Enhancer
         * */
        public Object getProxy(Class clazz){
            enhancer.setSuperclass(clazz);
            enhancer.setCallback(this);
            return enhancer.create();
        }
        
        /**
         * @author WesTward
         * @param proxied:被代理对象,目标对象,父类对象
         * @param method: 目标对象的 方法
         * @param args: 目标对象的方法的参数
         * @param proxy: 代理对象
         * */
        @Override
        public Object intercept(Object proxied, Method method, Object[] args,
                MethodProxy proxy) throws Throwable {
            System.out.println("Log---------start");
            proxy.invokeSuper(proxied, args);
            System.out.println("Log---------end");
            return null;
        }
    
    }

    测试类:

    package com.wtd.cglibproxy;
    
    public class Test {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            CglibProxy cglibProxy= new CglibProxy();
            Car car = (Car) cglibProxy.getProxy(Car.class);
            car.move();
        }
    
    }

    output:

    Log---------start
    the car running
    Log---------end

     附:

    动态代理主要运用了java的反射机制。

  • 相关阅读:
    网页元素居中的n种方法
    Swifter.Json 可能是 .Net 平台迄今为止性能最佳的 Json 序列化库【开源】
    .NET 欢乐编程术之类型超级转换之术👍👍
    C#.Net 使用 JsonReader/JsonWriter 高性能解析/生成 Json 文档
    UTF-16 -- 顶级程序员也会忽略的系统编码问题,JDK 错了十年!
    迄今为止 .Net 平台功能最强大,性能最佳的 JSON 序列化和反序列化库。
    并发系列(一)——线程池源码(ThreadPoolExecutor类)简析
    Flink源码阅读(一)——Per-job之Yarn的作业调度(一)
    阅读GitHub源码的正确打开方式
    安装Elasticsearch+Kibana【单节点、多ES实例】
  • 原文地址:https://www.cnblogs.com/westward/p/5437120.html
Copyright © 2011-2022 走看看