美文网首页
设计模式_代理_动态代理

设计模式_代理_动态代理

作者: 刘_120b | 来源:发表于2019-05-24 08:53 被阅读0次

1.代理模式概述

1.1什么是代理模式

ProxyPattern(即:代理模式)23种常用的面向对象软件的设计模式之一。
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
作用:增强一个类中的某个方法.对程序进行扩展. Spring框架中AOP.

1.2动态代理介绍

动态代理它可以直接给某一个目标(被代理 对象)对象(实现了某个或者某些接口)生成一个代理对象,而不需要代理类存在。
动态代理与代理模式原理是一样的,只是它没有具体的代理类,直接通过反射生成了一个代理对象。

动态代理的分类

  • jdk提供一个Proxy类可以直接给实现接口类的对象直接生成代理对象
  • spring中动态代理:cglib

2.jdk中的动态代理的使用

2.1API介绍

Java.lang.reflect.Proxy类可以直接生成一个代理对象

Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)生成一个代理对象
参数1:ClassLoader loader 代理对象的类加载器 一般使用被代理对象的类加载器
参数2:Class<?>[] interfaces 代理对象的要实现的接口 一般使用的被代理对象实现的接口
参数3:InvocationHandler h (接口)执行处理类

InvocationHandler中的invoke(Object proxy, Method method, Object[] args)方法:调用代理类的任何方法,此方法都会执行
-参数3.1Object proxy:代理对象(慎用)
-参数3.2Method method:当前执行的方法
-参数3.3Object[] args:当前执行的方法运行时传递过来的参数
返回值:当前方法执行的返回值

2.2代码实现

/**  规范接口
 * Created by liangtong.
 */
public interface Actor {
    /**
     * 唱歌
     * @return
     */
    public String sing();

    /**
     * 跳舞
     * @return
     */
    public String dance();
}
/** 目标类:刘德华类,需要被代理的类。
 * Created by liangtong.
 */
public class Liudehua implements Actor {
    @Override
    public String sing() {
        return "华仔唱歌";
    }

    @Override
    public String dance() {
        return "华仔跳舞";
    }
}
public class TestProxy {
    /*
    1.工具类 Proxy.newProxyInstance(); 运行时创建代理类
        Object object = Proxy.newProxyInstance()
    2. 参数
        参数1:类加载器,负责将新创建的类添加到内存中。
        参数2:确定需要实现接口们,java可以多实现,需要同一个数组。
        参数3:处理类,接口InvocationHandler
            //调用代理类的每一个方法,都将执行处理类的invoke方法。
            参数a) proxy 代理类,一般没用
            参数b) method 当前执行的方法
            参数c) args 方法的实际参数
 */
    @Test
    public void testDemo2(){
        //目标类
        Actor target = new Liudehua();
        //1 类加载  代理对象的类加载器  责将新创建的类添加到内存中
        ClassLoader classLoader = TestProxy.class.getClassLoader();
        //2 接口   代理对象的要实现的接口
        Class[] interfaces = {Actor.class};
        //3 处理类,接口InvocationHandler
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("代理收钱之后!");
                return method.invoke(target,args);
            }
        };
        //创建目标类
        Actor actor = (Actor) Proxy.newProxyInstance(classLoader,interfaces,invocationHandler);
        //调用方法并打印
        System.out.println(actor.sing());
        System.out.println(actor.dance());
    }
}

2.4代码实现(加强)

public interface Person {

    void eat();

    void sleep(Integer hours);
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Wash {

}
public class Student implements Person {
    @Override
    public void eat() {
        System.out.println("学生在吃饭");
    }

    @Wash
    @Override
    public void sleep(Integer hours) {
        System.out.println("学生在睡觉,睡了" + hours + "个小时");
    }
}
public class PersonFactory {

    public static Person getPerson() {
        //增强
        Student student = new Student();
        ClassLoader classLoader = student.getClass().getClassLoader();
        Class<?>[] interfaces = student.getClass().getInterfaces();

        Person obj = (Person) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {

            /**
             *
             * @param proxy 代理对象
             * @param method 代理方法
             * @param args 调用代理方法时传递的参数
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                Class<?>[] argClass = null;
                if (args != null) {
                    argClass = new Class[args.length];
                    //获取所有参数的类型
                    for (int i = 0; i < args.length; i++) {
                        argClass[i] = args[i].getClass();
                    }
                }

                //获取方法名
                String methodName = method.getName();

                //获取原始的方法
                Method originMethod = student.getClass().getMethod(methodName, argClass);
                System.out.println(originMethod);

                //判断方法是否需要增强
                if (originMethod.isAnnotationPresent(Wash.class)) {
                    System.out.println("之前洗漱");

                    Object obj = method.invoke(student, args);

                    System.out.println("之后洗漱");
                    return obj;
                }

                return method.invoke(student, args);
            }
        });
        return obj;
    }
}
public class StudentTest {
    @Test
    public void test() {
        Person person = PersonFactory.getPerson();
        person.eat();
        person.sleep(8);
    }
}

相关文章

  • 设计模式之代理模式

    设计模式之代理模式 10分钟看懂动态代理设计模式(升级篇)-对这篇动态代理模式的思路整理 仿JDK实现动态代理逻辑...

  • java动态代理(JDK和cglib)(转载自http://ww

    java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是...

  • Spring学习(五)AOP

    SpringAop使用到了了动态代理模式(有关设计模式见设计模式章节)。JDK动态代理代理的目标类必须要实现接口。...

  • Android 代理模式(动态代理)及其原理分析

    代理模式(动态代理)及其原理分析 概念 有一种设计模式叫做代理模式,其中也用到了动态代理。动态代理就是为某一个对象...

  • retrofit源码剖析

    设计模式:动态代理

  • Java代理模式之JDK动态代理

    了解什么是动态代理模式,可参考Java设计模式之代理模式 简介 JDK动态代理是java.lang.reflect...

  • 带你初识Java的代理模式

    Spring AOP是基于动态代理设计模式实现的,相对的就有静态代理 动态代理和静态代理 静态代理 对于静态代理,...

  • 代理模式

    结构型设计模式 代理模式 分类 静态代理:运行之前代理类的 class 编译文件已经存在 动态代理:通过反射动态...

  • Java设计模式之代理模式

    Java设计模式之代理模式 代理模式 静态代理 动态代理 为什么需要代理 通过代理,我们能够不用知道委托人是谁,而...

  • 代理模式

    代理模式感觉是一个复杂的设计模式,变种很多,如:远程代理、虚拟代理、静态代理、动态代理、安全代理等; 定义### ...

网友评论

      本文标题:设计模式_代理_动态代理

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