代理模式

Posted Ycheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代理模式相关的知识,希望对你有一定的参考价值。

  在Spring框架中有一个非常核心的思想就是Spring 中的AOP思想。其主要功能为:日志记录,性能统计,安全控制,事务处理,异常处理等等。

  AOP为Aspect Oriented Programming的缩写,意为:面向切面编程

                1) AOP是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构

                2)AOP最早由AOP联盟的组织提出的,制定了一套规范.Spring将AOP思想引入到框架中,必须遵守AOP联盟的规范

                3)通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术

                4)利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
  原理:AOP底层实现技术就是代理模式。
   
代理模式的分类:
  静态代理、动态代理、子类代理
 
/**
 * 目标接口
 */
public interface IUserDao {
    public void save();
    public void update();
}
/**
 * 目标类*/
public class UserDao implements IUserDao {
    @Override
    public void save() {
        System.out.println("保存用户");
    }
    @Override
    public void update() {
        System.out.println("更新用户");
    }
}
 
静态代理(了解):
 
 
// AOP编程- 静态代理写法
    @Test
    public void test2() {
        // 目标对象
        IUserDao userDao = new UserDao();
        // 代理类对象
        IUserDao userProxy = new MyUserDaoProxy(userDao);
        // 使用代理类的方法
        userProxy.save();
        userProxy.update();
    }
 
/**
 * 代理类(静态代理)
 * 静态代理类写法步骤:
 * 1)编写一个代理类,实现目标接口(和目标对象一样的接口)
 * 2)创建或者传入目标类对象
 * 3) 重写或者增强目标类的方法
 */
public class MyUserDaoProxy implements IUserDao{
    private IUserDao target;
    public MyUserDaoProxy(IUserDao target){
        this.target  = target;
    }
    @Override
    public void save() {
        System.out.println("记录日志");
        target.save();
    }
    @Override
    public void update() {
        System.out.println("记录日志");
        target.update();
    }
}

动态代理:

// AOP编程- 动态代理写法
    @Test
    public void test3() {
        // 目标对象
        IUserDao userDao = new UserDao();
        // 从工具类获取代理类对象
        IUserDao userProxy = (IUserDao)ProxyUtil.getProxy(userDao);
        System.out.println(userProxy.getClass());
        // 使用代理类的方法
        userProxy.save();
        userProxy.update();
    }
/**
 * 动态代理类生成工具
 */
public class ProxyUtil {
    /**
     * 用于生成(动态)代理类
     * @param target 目标类对象
     * @return 生成后的代理类对象
     */
    public static Object getProxy(final Object target){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),// 类加载器。和目标对象的类加载器一致了! 
                target.getClass().getInterfaces(), //接口列表,和目标对象的接口一致了!
                //匿名内部类
                new InvocationHandler() {
                    //该方法在每次调用代理类的方法时都会执行!
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                        //System.out.println("=========="+method.getName());
                        System.out.println("记录日志");
                        //调用目标类的方法
                        /**
                         * 参数一:执行方法的对象
                         * 参数二:方法的参数列表
                         */
                        Object result = method.invoke(target, args);
                        return result;
                    }
                }
                );
    }
}

子类代理(可利用子类代理):

// AOP编程- 子类代理写法
    @Test
    public void test4() {
        // 目标对象
        UserDao2 userDao = new UserDao2();
        // 从工具类获取代理类对象
        UserDao2 userProxy = (UserDao2)SubProxyUtil.getProxy(userDao);
        System.out.println(userProxy.getClass());
        // 使用代理类的方法
        userProxy.save();
        userProxy.update();
    }
/**
 * 生成子类代理类对象的工具
 */
public class SubProxyUtil {
    /**
     * 生成某个类的子类对象
     * @param target 目标类(目标类可以不用接口)
     * @return 子类代理对象
     */
    public static Object getProxy(final Object target){
        //创建Enhancer对象
        Enhancer eh = new Enhancer();
        //设置父类
        eh.setSuperclass(target.getClass());
        //设置代理后的处理程序(类似Proxy的InvocationHandler)
        eh.setCallback(new MethodInterceptor() {
            //每次代理的方法调用都会执行
            @Override
            public Object intercept(Object arg0, Method method, Object[] args,
                    MethodProxy arg3) throws Throwable {
                //System.out.println("========"+method.getName());
                System.out.println("记录日志");
                //调用目标类的方法
                method.invoke(target, args);
                return null;
            }
        });
        //创建子类代理对象
        return eh.create();
    }
}

spring AOP主要使用动态代理和利用cglib实现子类代理。

以上是关于代理模式的主要内容,如果未能解决你的问题,请参考以下文章

scrapy按顺序启动多个爬虫代码片段(python3)

用于从 cloudkit 检索单列的代码模式/片段

java代码实现设计模式之代理模式

代理模式(静态代理动态代理)代码实战(详细)

Java设计模式-代理模式之动态代理(附源代码分析)

代理模式(静态代理)