视频版 - 看着更方便:
哔哩哔哩(横板)👉 https://b23.tv/CvCn35C
小红书(竖版)👉 http://xhslink.com/GWMlCi
其实 代理模式 的思路非常好理解
"代理"这个词
我们在网购的时候应该经常会听到
比如:
“我们是 某某品牌的 代理商”
“你在我这里消费可以 领取优惠券 更便宜"
01 | 代理模式
所以代理模式就是说
我在 消费 某个方法的时候
不直接调用 方法所在类
而是通过中间的 代理类
在不改变原方法的基础上
对 原方法 增加额外的附加功能
这种"代理"的思想在实际开发中的典型应用就是 代码解耦 了
什么意思呢?
我们知道在开发中 除了 业务处理代码 还有一些 公共处理代码
像 记录日志......
这类代码其实完全没有必要和业务处理代码耦合在一起
所以可以应用 代理模式
将之解耦,放到代理类中
这样既不影响原方法
又能灵活的修改代理类
那接下来 我就以 记录日志 为例
演示一下 java应用 代理模式 的过程
02 | 静态代理
首先 定义一个消费接口以及它的实现类
其中包含一个“购物”方法
//接口
public interface ProducerService{
Product makeProduct();
}
//服务接口实现类
public class ProducerServicelmpl implements ProducerService{
@Override
public Product makeProduct(){
Product product =new Product();
return product;
}
}
然后 创建代理类 同样实现消费接口
//代理类
public class ProducerServiceProxy implements ProducerService{
//实例化被代理类
private ProducerService productService=new ProducerServicelmpl();
@Override
public Product makeProduct(){
//原方法
Product product=productService.makeProduct();
//日志记录逻辑代码
.....
return product;
}
}
在代理类中先实例化原来的实现类,也就是被代理类
接着重写 “购物”方法
在方法中 调用原"购物"方法的同时
增加额外的 日志记录 或其它功能
这样就实现了代理模式的一种
叫做 静态代理
静态代理的意思是
我们需要在代码编译运行之前预先创建好代理类
也就是说 如果我有十个类需要 记录日志
那就要预先写好十个代理类
这显然不是好的实现方式
于是引出了另一种代理模式的实现 动态代理
03 | 动态代理
动态代理的思路是
不需要预先写好代理类
而是编写一个公共的 代理配置类
然后在需要创建代理的时候
将 被代理类作为参数 传给 代理配置类
由代理配置类生成对应的 代理类
来看具体代码
//定义公共代理配置类
public class ProxyHandle implements InvocationHandle{
private Object prtoBeProxyService;
//构造函数
public ProxyHandle(Object toBeProxyService){
this.toBeProxyService=toBeProxyService;
}
@Override
public Object invoke(Object proxy,Method method,Object args) throws Throwable {
//执行原方法
Object invoke =method.invoke(subject,args)
//日志记录逻辑代码
.....
return invoke;
}
}
首先 创建一个 代理配置类
注意 它和普通类的区别是
必须实现 InvocationHandler 接口
它是java实现动态代理的关键
我们继续看里面的代码
先用构造函数来初始化被代理的对象
这里涉及一个知识点
Object 是 所有类的默认父类
也就是说下面这个等式是成立的:
class A{} = class A extends Object{};
所以 Object 可以接收任何类对象
接着重写 InvocationHandler 的 invoke方法
当我们调用原方法的时候
会被转发到这个方法中
所以这里就是我们对原方法进行功能扩展的地方了
其中入参
proxy 表示生成的代理类
method 表示原方法对象
args 表示原方法需要的参数
这就是 代理配置类 的代码了
接着我们看一下 调用动态代理 的示例代码:
//实例化服务
ProducerService producerService=new ProducerServicelmpl();
//创建代理配置类
ProxyHandle proxyHandle=newProxyHandle(producerService);
//生成代理类
ProducerService proxylnstance=(ProducerService)Proxy.newProxyinstance(
producerService.getClass().getClassLoader()
,producerService.getClass().getinterfaces()
,proxyHandle);
//调用方法
proxylnstance.makeProduct()
1、先创建被代理类实例
2、将被代理类作为入参,创建 代理配置类 实例
3、调用 Proxy 类的 newProxyInstance 方法创建代理类
这个Proxy类 是用来创建 代理类 的一个工具类
4、拿着上一步生成的动态代理类,调用目标方法
这个时候就会进入 代理配置类 的invoke方法执行代理逻辑
总结一下动态代理的实现
重写 InvocationHandler 的 invoke方法
然后调用 Proxy 工具类 创建代理对象
以上是基于 接口 来实现的动态代理(由jdk提供)
你可以看到必须要实现接口
04 | cglib
而另一种不基于接口的实现方式叫做: cglib
cglib 是一款开源的代码生成类库
可以动态的为普通类生成代理
所以在spring 中
如果目标类实现了接口,则使用jdk的方式来实现动态代理
如果没有实现接口,则使用cglib的方式来实现
我是浩说
帮你入门到放弃