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

2019-05-24  本文已影响0人  刘_120b

1.代理模式概述

1.1什么是代理模式

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

1.2动态代理介绍

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

动态代理的分类

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);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读