1.概念
①介绍
二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。
使用代理后:
②生活中的代理
- 广告商找大明星拍广告需要经过经纪人
- 合作伙伴找大老板谈合作要约见面时间需要经过秘书
- 房产中介是买卖双方的代理
-
③相关术语
代理:将非核心逻辑剥离出来以后,封装这些非核心逻辑的类、对象、方法。
- 目标:被代理“套用”了非核心逻辑代码的类、对象、方法。
理解代理模式、AOP的核心关键词就一个字:套
2、静态代理
3、动态代理
①生产代理对象的工厂类
/ 泛型T要求是目标对象实现的接口类型,本代理类根据这个接口来进行代理public class LogDynamicProxyFactory<T> {// 将被代理的目标对象声明为成员变量private T target;public LogDynamicProxyFactory(T target) {this.target = target;}public T getProxy() {// 创建代理对象所需参数一:加载目标对象的类的类加载器ClassLoader classLoader = target.getClass().getClassLoader();// 创建代理对象所需参数二:目标对象的类所实现的所有接口组成的数组Class<?>[] interfaces = target.getClass().getInterfaces();// 创建代理对象所需参数三:InvocationHandler对象// Lambda表达式口诀:// 1、复制小括号// 2、写死右箭头// 3、落地大括号InvocationHandler handler = (// 代理对象,当前方法用不上这个对象Object proxy,// method就是代表目标方法的Method对象Method method,// 外部调用目标方法时传入的实际参数Object[] args)->{// 我们对InvocationHandler接口中invoke()方法的实现就是在调用目标方法// 围绕目标方法的调用,就可以添加我们的附加功能// 声明一个局部变量,用来存储目标方法的返回值Object targetMethodReturnValue = null;// 通过method对象获取方法名String methodName = method.getName();// 为了便于在打印时看到数组中的数据,把参数数组转换为ListList<Object> argumentList = Arrays.asList(args);try {// 在目标方法执行前:打印方法开始的日志System.out.println("[动态代理][日志] " + methodName + " 方法开始了,参数是:" + argumentList);// 调用目标方法:需要传入两个参数// 参数1:调用目标方法的目标对象// 参数2:外部调用目标方法时传入的实际参数// 调用后会返回目标方法的返回值targetMethodReturnValue = method.invoke(target, args);// 在目标方法成功后:打印方法成功结束的日志【寿终正寝】System.out.println("[动态代理][日志] " + methodName + " 方法成功结束了,返回值是:" + targetMethodReturnValue);}catch (Exception e){// 通过e对象获取异常类型的全类名String exceptionName = e.getClass().getName();// 通过e对象获取异常消息String message = e.getMessage();// 在目标方法失败后:打印方法抛出异常的日志【死于非命】System.out.println("[动态代理][日志] " + methodName + " 方法抛异常了,异常信息是:" + exceptionName + "," + message);}finally {// 在目标方法最终结束后:打印方法最终结束的日志【盖棺定论】System.out.println("[动态代理][日志] " + methodName + " 方法最终结束了");}// 这里必须将目标方法的返回值返回给外界,如果没有返回,外界将无法拿到目标方法的返回值return targetMethodReturnValue;};// 创建代理对象T proxy = (T) Proxy.newProxyInstance(classLoader, interfaces, handler);// 返回代理对象return proxy;}}
