zoukankan      html  css  js  c++  java
  • 设计模式-动态代理

    1.Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:


    (1)Interface InvocationHandler:该接口中仅定义了一个方法
    public object invoke(Object obj,Method method, Object[] args)
    在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。 这个抽象方法在代理类中动态实现。

    (2)Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容

    protected Proxy(InvocationHandler h):构造函数,用于给内部的h赋值。

    static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

    static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)

    所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作

    创建动态代理步骤:

    1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
    2.创建被代理的类以及接口
    3.通过Proxy的静态方法 newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 创建一个代理
    4.通过代理调用方法

    动态代理的优点:

    可以很方便的实现解耦, 在AOP底层的主要就是通过java的这个动态代理实现的.

    举例说明动态代理:

    1.创建java项目

    2.创建一个被代理的接口

    package com.proxy.dynamicProxy;
    
    public interface Foo
    {
        public int deleteUserById(int userId);
        
        public void findAllUser();
        
    }

    3.创建被代理接口的实现类

    package com.proxy.dynamicProxy;
    
    public class FooImpl implements Foo
    {
    
        @Override
        public int deleteUserById(int userId)
        {
            System.out.println("删除用户业务开始..");
            return 1;
        }
    
        @Override
        public void findAllUser()
        {
            System.out.println("查询所有用户业务开始..");
        }
    }

    4. 创建一个InvocationHandler实现类

    package com.proxy.dynamicProxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    
    public class ComonInvocationHandler implements InvocationHandler
    {
        private Object obj; //代理目标对象
        
        public ComonInvocationHandler(){
            
        }
        public ComonInvocationHandler(Object target)
        {
            obj = target;
        }
    
        @Override
        //执行动态代理的所有方法时,都会被替换成执行如下的invoke方法
        /**
         * 参数说明:
         * proxy:动态代理对象
         * method:代表正在执行的方法
         * args:代表执行代理对象方法时传入的参数
         */
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable
        {
            System.out.println("before calling......");
            System.out.println("执行的方法名: "+method.getName());
            Object result = method.invoke(obj, args);
            
            System.out.println("after calling.....");
            return result;
            
        }
    
    }

    5.创建一个用于为指定目标对象生成代理对象的类

    package com.proxy.dynamicProxy;
    import java.lang.reflect.Proxy;
    /**
     * 该类用于为指定代理类生成动态代理实例
     *  Proxy.newProxyInstance(loader, interfaces, h):该方法创建一个动态代理对象,该代理对象的实现类
             实现了interfaces指定的系列接口, 执行代理对象的每个方法时都会被替换成执行InvocationHandler对象的invoke方法
     * loader - 定义代理类的类加载器
     * interfaces - 代理类要实现的接口列表
     * 指派方法调用的调用处理程序 
     */
    public class ProxyFactory
    {
        public static Object getProxy(Object target)
        {
            Class<?> classType = target.getClass();
            ComonInvocationHandler handler = new ComonInvocationHandler(target);
            
            return Proxy.newProxyInstance(classType.getClassLoader(), 
                    classType.getInterfaces(), handler);
        }
    }

    6.测试类

    package com.proxy.dynamicProxy;
    
    public class Client
    {
        public static void main(String[] args)
        {
           //创建Foo的一个实现,作为target
           Foo foo = new FooImpl();
           
           //以指定的target来创建代理对象
           Foo proxyFoo = (Foo) ProxyFactory.getProxy(foo);
           
           System.out.println("执行删除的结果: "+proxyFoo.deleteUserById(1));
           proxyFoo.findAllUser();
           
        }
    }
  • 相关阅读:
    windows 按时自动化任务
    Linux libusb 安装及简单使用
    Linux 交换eth0和eth1
    I.MX6 GPS JNI HAL register init hacking
    I.MX6 Android mmm convenient to use
    I.MX6 GPS Android HAL Framework 调试
    Android GPS GPSBasics project hacking
    Python windows serial
    【JAVA】别特注意,POI中getLastRowNum() 和getLastCellNum()的区别
    freemarker跳出循环
  • 原文地址:https://www.cnblogs.com/david-rui/p/3634594.html
Copyright © 2011-2022 走看看