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

    一,静态代理(房产中介)

    在代理模式中的角色:

      ●  抽象对象角色:声明了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象。

      ●  目标对象角色:定义了代理对象所代表的目标对象。

      ●  代理对象角色:代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象。代理对象通常在客户端调用传递给目标对象之前或之后,执行某个操作,而不是单纯地将调用传递给目标对象。

    /**
     * 抽象角色,真实角色和代理角色都要实现的接口
     * @author marcopan
     */
    public interface IAbstractSubject {
    
        // 代理对象和真实角色共有的方法,租房()
        public void rentHouse();
    }
    
    /**
     * 真实角色--房东
     * @author marcopan
     *
     */
    public class RealSubject implements IAbstractSubject {
    
        @Override
        public void rentHouse() {
            System.out.println("rentHouse from RealSubject");
        }
    }
    
    package proxy.staticProxy;
    
    /**
     * 代理角色,中介,含有真实角色的引用
     * @author marcopan
     * 代理角色做两件事:
     * 1. 关联真实角色对象
     * 2. 调用真实对象方法
     */
    public class StaticProxySubject implements IAbstractSubject {
        // 含有真实角色的引用
        private RealSubject realSubject = null;
    
        public StaticProxySubject(RealSubject subject) {
            this.realSubject = subject;
        }
    
        @Override
        public void rentHouse() {
            realSubject.rentHouse();
        }
    }
    
    public class Client {
        public static void main(String[] args) {
            IAbstractSubject proxySubject = new StaticProxySubject(new RealSubject());
            proxySubject.rentHouse();
        }
    }

    二,动态代理

    public class DynamicProxySubject implements InvocationHandler {
        private ISubject target = null;
    
        public DynamicProxySubject(ISubject target) {
            this.target = target;
        }
    
        public Object getProxyInstance() {
            Class<?> clazz = target.getClass();
            /**
             * Proxy这个类的作用就是用来动态创建一个代理对象的类
             * Proxy.newProxyInstance返回的是一个代理对象:com.sun.proxy.$Proxy0
             */
            return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
        }
    
        /**
         * proxy:指被代理的对象,$Proxy0是系统自动生成的实现ISubject接口的代理类,并持有InvocationHandler引用
         * method:指代的是我们所要调用真实对象的某个方法的Method对象
         * args:指代的是调用真实对象某个方法时接受的参数
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 增强消息......
            return method.invoke(target, args);
            // 增强消息......
        }
    }
    
    /**
     * //        byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{IAbstractSubject.class});
     * //        try {
     * //            String filePath = IAbstractSubject.class.getResource("").getPath();
     * //            FileOutputStream fos = new FileOutputStream(filePath + "/$Proxy0.class");
     * //            fos.write(bytes);
     * //            fos.close();
     * //        } catch (Exception e) {
     * //            e.printStackTrace();
     * //        }
     */
    
    
    public class Client {
        public static void main(String[] args) {
            ISubject target = new RealSubject();
            ISubject dynamicInstance = (ISubject) new DynamicProxySubject(target).getProxyInstance();
            dynamicInstance.requestHouse1();
            dynamicInstance.requestHouse2();
        }
    }
    

    三、Cglib动态代理:

    public class CglibProxySubject implements MethodInterceptor {
    
        public Object getCglibInstance(Class<?> clazz) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(clazz);
            enhancer.setCallback(this);
    
            return enhancer.create();
        }
    
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            // before
            Object obj = methodProxy.invokeSuper(o, objects);
            // after
            return obj;
        }
    }
    
    public class Client {
        public static void main(String[] args) {
            String filePath = ISubject.class.getResource("").getPath();
            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, filePath);
    
            ISubject target = new RealSubject();
            ISubject cglibInstance = (ISubject) new CglibProxySubject().getCglibInstance(target.getClass());
            System.out.println(cglibInstance);
            cglibInstance.requestHouse1();
            cglibInstance.requestHouse2();
        }
    }
    

    CGLib 和 JDK 动态代理对比:

    1.JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。

    2.JDK 和 CGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM 框架写 Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。

    3.JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法, CGLib 执行效率更高。

  • 相关阅读:
    C#如何不使用递归实现无限层次结构的代码分享[转]
    asp.net mvc2 templates的一篇文章
    asp.net mvc Model验证总结及常用正则表达式
    关于IE的Ajax请求结果缓存的问题
    在ASP.NET MVC中如何让ASCX用户控件具有Action / Controller
    Kubernetes之Pod介绍
    Docker 之Swarm介绍
    Docker之多机网络
    Kubernetes之Pod调度
    Docker之隔离技术
  • 原文地址:https://www.cnblogs.com/panning/p/7747754.html
Copyright © 2011-2022 走看看