参考资料
应用场景
- 在业务系统中开发一些非功能性需求,比如:监控、统计、鉴权、限流、事务、幂等、日志。将这些附加功能与业务功能解耦,放到代理类中统一处理,让程序员只需要关注业务方面的开发。
- RPC通过远程代理,将网络通信、数据编解码等细节隐藏起来。客户端在使用 RPC 服务的时候,就像使用本地函数一样,无需了解跟服务器交互的细节。
- 动态代理,基于不同情况,进行不同的调用
代理模式的实现方式
实现接口的方式
public interface IUser{
UserVo login(String telephone, String password);
}
public class User implements IUser{
@Override
public UserVo login(String telephone, String password){
//省略login逻辑
}
}
public class UserProxy implements IUser{
private User user;
//构造方法注入
public UserProxy(User user){
this.user = user;
}
@Override
public UserVo login(String telephone, String password){
//增强
long startTime = System.currentTimeMillis();
//原始
UserVo userVo = user.login(telephone, password);
//增强
long endTime = System.currentTimeMillis();
return userVo;
}
}
继承的方式
如果原始的类是来自第三方类库,无法修改,那么一般采用这种继承的方式
public class UserProxy extends IUser{
private User user;
//构造方法注入
public UserProxy(User user){
this.user = user;
}
@Override
public UserVo login(String telephone, String password){
//增强
long startTime = System.currentTimeMillis();
//原始
UserVo userVo = super.login(telephone, password);
//增强
long endTime = System.currentTimeMillis();
return userVo;
}
}
动态代理的方式
如果要添加的附加功能的类有不止一个,我们需要针对每个类都创建一个代理类,代码臃肿。
JDK动态代理
public interface Happy {
// 协议
void happy();
}
public class JinLian implements Happy {
// 被代理类
public void happy(){
System.out.println("金莲在happy...");
}
}
public class Test {
public static void main(String[] args) {
//static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)生成一个代理对象
//参数1ClassLoader: 被代理类的类加载器
//参数2interfaces: 被代理类实现的所有接口的字节码对象
//参数3InvocationHandler: 执行处理接口
//返回: 代理对象
//参数1和参数2是用来帮助生成对应的代理对象,参数3用来监听代理对象调用方法,帮助我们调用方法
//InvocationHandler接口:
//Object invoke(Object proxy, Method method, Object[] args)方法:调用代理类的任何方法,此方法都会执行
//参数1proxy: 代理对象,一般不用,忽略
//参数2method: 代理对象调用的方法
//参数3args: 代理对象调用方法传入的实际参数
//返回值:当前方法执行的返回值
JinLian jl = new JinLian();
// 获取金莲的代理对象
Happy proxy = (Happy)Proxy.newProxyInstance(JinLian.class.getClassLoader(), JinLian.class.getInterfaces(), new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 代理对象调用方法就会执行invoke方法
System.out.println("以做衣服的名义,帮2人开好房间...");
// 金莲happy
method.invoke(jl);
System.out.println("打扫战场...");
return null;
}
});
// 代理对象调用happy方法
proxy.happy();// void happy();
}
}