美文网首页
Java代理设计模式(Proxy)的几种具体实现

Java代理设计模式(Proxy)的几种具体实现

作者: rickJinzhu | 来源:发表于2019-12-18 18:33 被阅读0次

    Proxy是一种结构设计模型,主要解决对象直接访问带来的问题,代理又分为静态代理和动态代理(JDK代理、CGLIB代理。
    静态代理:又程序创建的代理类,或者特定的工具类,在平时开发中经常用到这种代理模式,这种一般在程序运行前就已经生成对应的class文件;
    动态代理:在程序运行时通过反射机制动态创建。

    下面通过一个场景实现以下三种代理方式

    • 步骤一:定义商店接口(Subject)
    • 步骤二:个人店家运营(RealSubject)
    • 步骤三:平台运营(proxy)
    • 步骤四:个体消费(client)


    几种代理方式都会用到Subject、RealSubject,现在这里定义
    Store.java(Subject):定义两个接口operate(运营),business(交易)。

    public interface Store {
        /**
         * 店铺运营
         */
        public void operate();
    
        /**
         * 店铺交易
         */
        public void business();
    }
    
    

    PersonStore.java(RealSubject) 单个用户运营

    public class PersonStore implements Store {
        @Override
        public void operate() {
            System.out.println("个人商店运营");
        }
    
        @Override
        public void business() {
            System.out.println("个人商店交易");
        }
    }
    

    静态代理

    静态代理的实现比较简单,代理类通过实现与目标对象相同的接口,并在类中维护一个代理对象,这种场景用于个体商家比较少的情况,如果多的话代理类十分繁多、不易维护

    创建静态代理类

    ProxyStroe.java(proxy):在代理平台运营是收取管理费用100,这个代理类需要实现Store接口,并制定目标类target(PersonStore)。

    public class ProxyStroe implements Store{
    
        private Store personStore = new PersonStore();
    
        @Override
        public void operate() {
            System.out.println("收取管理费用100元");
            personStore.operate();
        }
    
        @Override
        public void business() {
            personStore.business();
        }
    }
    

    静态代理调用

    StaticConsumer.java(client):通过创建ProxyStroe去代理PersonStore,并进行操作。

    public class StaticConsumer {
    
        public static void main(String[] args) {
            ProxyStroe store = new ProxyStroe();
            store.operate();
            store.business();
        }
    }
    

    动态代理

    JDK代理

    动态代理类是通过接口实现的,利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,
    在调用具体方法前调用InvokeHandler来处理。

    创建jdk代理类

    JDKStoreHandler.java(proxy):通过实现InvocationHandler接口的invoke方法,在里面进行反射调用,newProxyInstanse通过目标对象创建真是对象。

    public class JDKStoreHandler implements InvocationHandler {
    
        /**
         * 目标对象
         */
        private Object targetObject;
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if("operate".equals(method.getName())){
                System.out.println("收取管理费用100元");
            }
            return method.invoke(targetObject, args);
        }
    
        /**
         *
         * @param targetObject
         * @return
         */
        public Object newProxyInstanse(Object targetObject){
            this.targetObject = targetObject;
            return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);
        }
    }
    

    JDK代理对象调用

    JDKDynamicConsumer.java(proxy):通过JDKStoreHandler的newProxyInstanse创建真实目标对象,并调用接口的方法

    public class JDKDynamicConsumer {
    
        public static void main(String[] args) {
            Store store = (Store)new JDKStoreHandler().newProxyInstanse(new PersonStore());
            store.operate();
            store.business();
        }
    }
    
    

    CGLIB代理

    cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

    创建cglib代理对象

    CglibProxy.java(proxy):需要实现MethodInterceptor的intercept方法,并进行反射调用。通过createProxyObject创建真实对象,这里是根据目标对象直接生成对象。

    public class CglibProxy implements MethodInterceptor{
    
        /**
         * CGlib需要代理的目标对象
         */
        private Object targetObject;
    
        public Object createProxyObject(Object targetObject){
            this.targetObject = targetObject;
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(targetObject.getClass());
            enhancer.setCallback(this);
            Object proxyObj = enhancer.create();
            return proxyObj;
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            if("operate".equals(method.getName())){
                System.out.println("收取管理费用100元");
            }
            return method.invoke(targetObject, objects);
        }
    }
    

    CGLib代理对象调用

    CglibDynamicConsumer.java(client):通过CglibProxy的createProxyObject创建真实目标对象,对进行方法调用

    public class CglibDynamicConsumer {
    
        public static void main(String[] args) {
            Store store = (Store)new CglibProxy().createProxyObject(new PersonStore());
            store.operate();
            store.business();
        }
    }
    
    

    源码已上传:https://github.com/itrickzhang/proxy-demo

    本文由博客一文多发平台 OpenWrite 发布!

    相关文章

      网友评论

          本文标题:Java代理设计模式(Proxy)的几种具体实现

          本文链接:https://www.haomeiwen.com/subject/kzgunctx.html