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

    代理模式,主要分为静态代理和动态代理,本质上都是在不改变目标对象的结构、功能的前提下,对目标对象的功能进行增强。

    一、静态代理

      描述:目标对象和代理对象都实现同一个接口或者同一父类。可以实现在不修改目标对象的基础上,增强目标对象的处理功能。

      缺点:固化。可能会存在大量的目标对象和代理对象。并且,如果接口变动的话,那么所有的目标对象和代理对象都必须得修改,不灵活,扩展维护性差。

      简单代码演示:

        接口类:

    package com.cn.agent.staticAgent.byInterface;
    
    public interface IUserDao {
    
        void save();
    }

        目标类:

    package com.cn.agent.staticAgent.byInterface;
    
    /**
     * 目标对象类
     * @author cfang
     * 2018年5月25日 下午3:50:56
     */
    public class UserDao implements IUserDao{
    
        public void save(){
            System.out.println("--- 调用目标对象方法 ---");
        }
    }

        代理类:

    package com.cn.agent.staticAgent.byInterface;
    
    /**
     * 静态代理类
     * @author cfang
     * 2018年5月25日 下午3:50:44
     */
    public class UserDaoProxy implements IUserDao{
    
        //接收并保存目标对象
        private IUserDao target;
        public UserDaoProxy(IUserDao target){
            this.target = target;
        }
        
        @Override
        public void save(){
            System.out.println("--- 代理对象类方法调用开始  ---");
            target.save();
            System.out.println("--- 代理对象类方法调用结束  ---");
        }
    }

      测试main方法

    package com.cn.agent.staticAgent.byInterface;
    
    public class App {
    
        public static void main(String[] args) {
            //目标对象
            IUserDao target = new UserDao();
            //代理对象
            IUserDao proxy = new UserDaoProxy(target);
            
            proxy.save();
        }
    }

    二、动态代理

      描述:目标对象和静态代理相同。代理对象无需实现接口。代理对象的生成,通过jdk的java.lang.reflect.Proxy中的newProxyInstance方法去产生。

      简单代码演示:

      接口类、目标类代码同静态代理中定义。

      代理类

    package com.cn.agent.dynamicAgent;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyFactory {
    
        //存放目标对象类
        private Object target;
        public ProxyFactory(Object target){
            this.target = target;
        }
        
        //生成代理对象
        public Object getProxyInstance(){
            return Proxy.newProxyInstance(
                    target.getClass().getClassLoader(), //ClassLoader -- 
                    target.getClass().getInterfaces(),  //Class<?>[] interfaces -- 
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("代理类方法执行开始");
                            Object result = method.invoke(target, args);
                            System.out.println("代理类方法执行结束");
                            return result;
                            
                        }
                    });
        }
    }

      测试main方法

    package com.cn.agent.dynamicAgent;
    
    public class App {
    
        public static void main(String[] args) {
            
            //目标对象类
            IUserDao target = new UserDao();
            System.out.println("原始目标对象类:" + target.getClass());
            
            //代理对象类
            IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
            System.out.println("代理对象类:" + proxy.getClass());
            
            proxy.save();
        }
    }

    三、cglib代理

      描述:静态代理和动态代理,都要求目标对象去实现一个接口。但是,有时候,目标对象只是个单独的类对象。这时候,可以利用cglib代理,在内存中虚构一个目标对象的子类对象,从而实现对目标对象的功能增强。

      简单代码演示

      目标类

    package com.cn.agent.cglibAgent;
    
    public class UserDao {
    
        public void save(){
            System.out.println("--- 我是目标对象类非final方法 ---");
        }
        
        public final void save2(){
            System.out.println("--- 我是目标对象类final方法 ---");
        }
        
        public String save3(){
            System.out.println("--- 我是有返回的方法 ---");
            return "hello world";
        }
        
        public String save4(String param){
            System.out.println("--- 我是带参的有返回的方法 ---");
            return param;
        }
    }

      代理类

    package com.cn.agent.cglibAgent;
    
    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.Callback;
    import net.sf.cglib.proxy.CallbackFilter;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    /**
     * Enhancer - 主要的增强类
     * MethodInterceptor - 方法拦截类,继承自Callback接口
     * @author cfang
     * 2018年5月25日 下午5:26:49
     */
    public class ProxyFactory implements MethodInterceptor{
    
        //存放目标对象类
        private Object target;
        
        public ProxyFactory(Object target){
            this.target = target;
        }
        
        //创建代理类
        public Object getProxyInstance(){
            //基本工具类 :设置回调函数、设置父类、生成代理子类
            Enhancer enhancer = new Enhancer();
            //设置父类 : 设置生成的代理对象的父类
            enhancer.setSuperclass(target.getClass());
            //设置回调 : Callback接口的实例
            enhancer.setCallback(this);
            
            //设置多组回调
    //        Callback[] callbacks = new Callback[]{this,this};
    //        enhancer.setCallbacks(callbacks);
            //回调选择器,根据不同返回值,调用callbacks中不同的回调。返回值和callbacks回调的下标对应
    //        enhancer.setCallbackFilter(new TestFilter());
            //生成子类
            return enhancer.create();
        }
    
        /**
         * 拦截增强方法
         */
        @Override
        public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy proxy) throws Throwable {
            System.out.println("proxy:" + proxy);
            System.out.println("--- 代理对象增强方法开始 ---");
            
    //        Object result = method.invoke(target, arg2);
            Object result = proxy.invokeSuper(arg0, arg2);
            
            System.out.println("--- 代理对象增强方法结束 ---");
            return result;
        }
        
        
    }

      测试main方法

      

    package com.cn.agent.cglibAgent;
    
    public class App {
    
        public static void main(String[] args) {
            
            //目标对象
            UserDao target = new UserDao();
            //代理对象
            UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();
            
            proxy.save();
            
            proxy.save2();
            
            System.out.println(proxy.save3());
            
            System.out.println(proxy.save4("Test"));
            
        }
    }

    ps:spring中,基于接口的都是利用jdk动态代理,而其他都是利用cglib的代理机制。

      水平有限,欢迎指正。

  • 相关阅读:
    053-509
    053-298
    053-255
    css实现省略号
    github上写blog
    解决内容被挤压缩小问题
    request.getRequestDispather().forward()与response.sendRedirect()
    资料,来自HTML5前端开发学习⑤群
    checkbox与jq<转>2
    checkbox与jq<转>
  • 原文地址:https://www.cnblogs.com/eric-fang/p/9101501.html
Copyright © 2011-2022 走看看