精品课程网站建设意义流量购买网站
目录儿
- 一、代理模式的作用
- 二、实现代理的方式
- 三、动态代理的实现
- 3.1 jdk动态代理
- 3.2 cglib动态代理
一、代理模式的作用
- 功能增强: 基于某个功能,再增加一些功能。
(比如目标类只负责核心功能,其他附属功能通过代理类完成。代理类的方法名与目标类的方法相同,内容不同,在核心功能外加了一些额外逻辑) - 控制访问: 防止直接访问目标。
代理类代理目标类
目标类是实现目标功能的类
二、实现代理的方式
-
动态代理:
- 特点:
- 在程序执行过程中,自动使用
jdk
反射机制创建代理对象(而不需要写.java源文件),并且动态指定要代理的目标类。
- 在程序执行过程中,自动使用
- 优点:
- 缺点
- 特点:
-
静态代理:
- 特点:
- 代理类是自己手动实现的。自己创建一个类作为代理类
- 要代理的目标类是确定的。
- 优点:
- 实现简单,容易理解
- 在不改变原目标对象代码的情况下,对目标的功能进行拓展
- 缺点:
- 当目标类增加了,代理类可能要成倍的增加,代理类过多
- 当接口的功能增加或修改,会影响所有实现类,修改工作量大,不好管理维护 。
- 特点:
三、动态代理的实现
3.1 jdk动态代理
基于接口实现代理
使用java
反射包中的接口和类实现动态代理,要求 代理类和工具类实现同一个接口。
其中反射包是java.lang,reflect
,里面有三个类:InvocationHandler
、Method
、Proxy
① 创建目标接口
public interface Star{String sing(String name);void dance();
}
② 创建目标类实现目标接口
public class BigStar implements Star {private String name;public BigStar(String name) {this.name = name;}public String sing(String name) {System.out.println(this.name + "正在唱歌儿:" + name);return "谢谢儿!谢谢儿!";}public void dance() {System.out.println(this.name + "正在跳舞儿");}
}
③ 创建对应的处理器实现InvocationHandler
接口,重写invoke
方法(里面写增强业务)
public class StarInvocationHandler<T> implements java.lang.reflect.InvocationHandler {private final T target; // 存储目标对象public StarInvocationHandler(T target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(method.getName() + "方法执行前增强");Object result = method.invoke(target, args);System.out.println(method.getName() + "方法执行后增强");return result;}
}
④ 创建工厂类,为了简化创建代理对象的过程(这里用了泛型约束,可以不用)
public class ProxyHandlerFactory {/*** 创建 Star 接口的代理对象*/public static <T extends Star> Star createStarProxy(T target) {return (Star) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new StarInvocationHandler<>(target));}}
⑤ 测试调用
public class Main {public static void main(String[] args) {BigStar bigstar = new BigStar("迪丽热巴");Star starProxy = ProxyHandlerFactory.createStarProxy(bigstar);String result = starProxy.sing("老公老公我爱你");System.out.println(result);}
}
结果:
3.2 cglib动态代理
基于继承实现代理
cglib
是一个第三方工具库,能够创建代理对象。
通过继承的方式实现动态代理,通过继承目标类,创建它的子类,在子类中重写父类的同名方法,实现功能的修改。(因为是继承重写的方式实现代理,因此要求目标类不能是final
修饰,要重写的方法也不能是final
修饰的)。
① 导入cglib
依赖
② 创建目标类
public class BigStar {private String name;public BigStar() {}public BigStar(String name) {this.name = name;}public String sing(String name) {System.out.println(this.name + "正在唱歌儿:" + name);return "谢谢儿!谢谢儿!";}public void dance() {System.out.println(this.name + "正在跳舞儿");}
}
③ 创建拦截器
public class BigStarMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println(method.getName() + "方法增强前");Object result = methodProxy.invokeSuper(o, objects); // 调用目标类方法System.out.println(method.getName() + "方法增强前");return result;}
}
④ 创建代理对象,测试
public class TestMain {@Testpublic void test() {// 创建与目标对象对应的拦截器BigStarMethodInterceptor bigStarMethodInterceptor = new BigStarMethodInterceptor();// 创建一个增强器对象Enhancer enhancer = new Enhancer();// 设置目标类enhancer.setSuperclass(BigStar.class);// 设置拦截处理器enhancer.setCallback(bigStarMethodInterceptor);// 创建代理对象(根据参数选择对应的 Constructor)BigStar bigStarProxy = (BigStar) enhancer.create(new Class[]{String.class}, new Object[]{"胖迪"});// 调用方法String s = bigStarProxy.sing("猪之歌");System.out.println(s);}
}
运行结果:
cglib
的代理效率高于jdk
代理。
如果想看看生成的代理对象长什么养,可以通过设置一个系统属性并指定路径,CgLib会把生成的代理对象写出到该位置:
// CgLib提供的代理类生成器System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\idea_workspace\\ruoyi\\wipinfo_bigscreen_manager\\admin\\src");
参考资料:
- 哔哩哔哩 黑马程序员磊哥 【黑马磊哥】Java动态代理深入剖析,真正搞懂Java核心设计模式:代理设计模式
https://www.bilibili.com/video/BV1ue411N7GX?share_source=copy_web
- 哔哩哔哩 动力节点 Java-JDK动态代理(AOP)使用及实现原理分析
https://www.bilibili.com/video/BV1HZ4y1p7F1?share_source=copy_web
- 哔哩哔哩 上云_云哥 jdk动态代理,cglib动态代理,代理设计模式,aop切面编程
https://www.bilibili.com/video/BV1tY411Z799?p=6&share_source=copy_web