- A+
Java互联网企业架构技术VIP课程【腾讯课堂每特】
设计模式的分类
Java互联网企业架构技术VIP课程【腾讯课堂每特】
课程内容
站在架构角度,基于装饰模式纯手写设计多级缓存框架
- 如何理解多级缓存框架设计
装饰模式与代理模式之间的区别
3.装饰模式如何在Mybatis、IO流运用
4.基于装饰设计多级缓存框架
5.自定义缓存注解,轻松搞定多级缓存问题
本节课需要知识:动态代理技术+Aop+装饰模式+Redis缓存概念
注意:因为该设计模式比较接近真实案例,需要有SpringBoot基础。
创建型模式
工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式
适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
行为模式
策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
彻底搞懂代理模式实现原理
什么是代理模式
代理模式主要对我们方法执行之前与之后实现增强
代理模式应用场景
- 日志的采集
- 权限控制
- 实现aop
- Mybatis mapper
- Spring的事务
- 全局捕获异常
- Rpc远程调用接口
- 代理数据源
代理模式创建方式
静态代理
静态代理需要自己人工编写代理类代码
基于接口实现方式
public class OrderServiceProxy implements OrderService{ public OrderServiceProxy(OrderService orderService) { public String addOrder(String userName, String userPwd) {
public interface OrderService {
public class Test001 {
|
基于继承的实现方式
public class OrderServiceProxy extends OrderServiceImpl { public OrderServiceProxy(OrderService orderService) { public String addOrder(String userName, String userPwd) {
|
动态代理与静态代理的区别
动态代理不需要写代理类对象,通过程序自动生成,而静态代理需要我们自己写代理类对象。
动态代理
动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成 。
Jdk动态代理
JDK动态代理的一般步骤如下:
1.创建被代理的接口和类;
2.实现InvocationHandler接口,对目标接口中声明的所有方法进行统一处理;
3.调用Proxy的静态方法,创建代理类并生成相应的代理对象;
实现原理:利用拦截器机制必须实现InvocationHandler接口中的invoke方法实现对
我们的目标方法增强。
public class JdkInvocationHandler implements InvocationHandler { public JdkInvocationHandler(Object target) { /** /** }
|
public class JdkInvocationHandler implements InvocationHandler { public JdkInvocationHandler(Object target) { /** public <T> T getProxy() { }
|
JdkInvocationHandler jdkInvocationHandler = new JdkInvocationHandler(new OrderServiceImpl());
|
加上该代码:
- 获取代理的生成的class文件
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
- 使用反编译工具该Pclass
|
注意:继承了Proxy类,实现了代理的接口,由于java不能多继承,这里已经继承了Proxy类了,不能再继承其他的类,所以JDK的动态代理不支持对实现类的代理,只支持接口的代理。
纯手写Jdk动态代理
思路分析:
- 定义InvocationHandler类 回调方法
- 使用java反射技术获取接口下所有的方法,拼接 $Proxy0.java代码
- 在将$Proxy0.java编译成class文件,读取到内存中
public class $Proxy0 implements com.mayikt.service.OrderService { private MayiktJdkInvocationHandler h; public $Proxy0(MayiktJdkInvocationHandler mayiktJdkInvocationHandler) { @Override static {
|
public class MyJdkInvocationHandler implements MayiktJdkInvocationHandler { public MyJdkInvocationHandler(Object target) { @Override } |
MyJdkInvocationHandler myJdkInvocationHandler = new MyJdkInvocationHandler(new OrderServiceImpl()); |
public class MyProxy { public static Object newProxyInstance(JavaClassLoader classLoader, Class classInfo, MayiktInvocationHandler mayiktInvocationHandler) { public static String getMethodString(Method[] methods, Class intf) { for (Method method : methods) { } public static void main(String[] args) {
|
public class JavaClassLoader extends ClassLoader { private File classPathFile; public JavaClassLoader(){ @Override
|
public class MyJdkInvocationHandler implements MayiktJdkInvocationHandler { public MyJdkInvocationHandler(Object target) { @Override public <T> T getProxy() {
|
CGLIB动态代理
利用asm字节码技术,生成子类实现对目标方法实现增强
实现方式
Maven依赖
<dependencies> |
核心代码
public class CglibMethodInterceptor implements MethodInterceptor {
|
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\code");
|
Cglib动态代理底层源码分析
Cglib依赖于ASM字节码技术,直接生成class文件,在采用类加载器读取到程序中,
使用fastclass对被代理类的方法建立索引文件不需要依赖于反射查找到目标方法,所以效率比Jdk动态代理要高。
public class OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c extends OrderServiceImpl { static void CGLIB$STATICHOOK1() throws ClassNotFoundException { final String CGLIB$addOrder$0(String s, String s1) { final boolean CGLIB$equals$1(Object obj) { final String CGLIB$toString$2() { final int CGLIB$hashCode$3() { public static void CGLIB$SET_THREAD_CALLBACKS(Callback acallback[]) { public final String addOrder(String paramString1, String paramString2) { CGLIB$BIND_CALLBACKS(this); public Object newInstance(Callback acallback[]) { public Object newInstance(Callback callback) { public void setCallback(int i, Callback callback) { private boolean CGLIB$BOUND; static { public OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c() { private void CGLIB$BIND_CALLBACKS(OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c orderServiceImpl$$EnhancerByCGLIB$$1dd3a71c) {
|
FastClass机制
public class MayiktFastclass { /** /** public static void main(String[] args) {
|
Jdk与Cglib动态代理的区别
- Jdk动态代理利用反射技术生成匿名的代理类走InvokeHandler回调方法实现增强,同时也是一种基于接口的方式实现代理。
- Cglib动态代理利用asm字节码技术生成一个子类覆盖其中的方法实现增强,同时采用fastClass机制对整个代理类建立索引比反射效率要高
- 在Spring中如果需要被代理的对象如果实现了接口采用Jdk动态代理,没有实现接口则使用Cglib动态代理。