在上一篇文章我们介绍了静态代理,动态代理和静态对比基本思路是一致的,只不过动态代理功能更加强大,随着业务的扩展适应性更强。一方面,我们需要在代理类中,将原始类中的所有的方法,都重新实现一遍,并且为每个方法都附加相似的代码逻辑。另一方面,如果要添加的附加功能的类有不止一个,我们需要针对每个类都创建一个代理类。
如果有 50 个要添加附加功能的原始类,那我们就要创建 50 个对应的代理类。这会导致项目中类的个数成倍增加,增加了代码维护成本。并且,每个代理类中的代码都有点像模板式的“重复”代码,也增加了不必要的开发成本。那这个问题怎么解决呢?
我们可以使用动态代理来解决这个问题。所谓动态代理(Dynamic Proxy),就是我们不事先为每个原始类编写代理类,而是在运行的时候,动态地创建原始类对应的代理类,然后在系统中用代理类替换掉原始类。
还是拿找对象的的例子,如果找对象这项业务发展成了一个产业,不仅仅只是父亲给儿子找对象,而是出现了媒婆、婚介所等这样的形式,可以满足任一单身人士的需求。
因为 Java 语言本身就已经提供了动态代理的语法(实际上,动态代理底层依赖的就是 Java 的反射语法),所以,我们升级一下代码:
// 实现 InvocationHandler 接口
public class JDKMeipo implements InvocationHandler {
// 被代理对象(依赖注入)
private Object target;
public Object getInstance(Object target) throws Exception{
this.target = target;
Class<?> clazz = target.getClass();
// 核心!
return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
// 调用被代理对象的当前方法
Object obj = method.invoke(this.target,args);
after();
return obj;
}
private void before(){
System.out.println("我是媒婆,负责找对象,现在已经确认需求");
System.out.println("开始物色");
}
private void after(){
System.out.println("OK的话,准备办事");
}
}
// 创建单身客户 Customer 类
public class Customer implements Person {
public void findLove() {
System.out.println("高富帅就行了");
}
}
测试代码:
public class JDKProxyTest {
public static void main(String[] args) {
try {
Person obj = (Person)new JDKMeipo().getInstance(new Customer());
obj.findLove();
}catch (Exception e){
e.printStackTrace();
}
}
}
运行结果如下:
我是媒婆,负责找对象,现在已经确认需求
开始物色
高富帅就行了
OK的话,准备办事
实际业务场景示例
我们下面再通过动态代理来改造一下上一篇讲过的动态路由代码…
创建动态代理的类 OrderServiceDynamicProxy,代码如下:
// 实现 InvocationHandler 接口
public class OrderServiceDynamicProxy implements InvocationHandler {
private SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");
// 被代理对象
Object proxyObj;
public Object getInstance(Object proxyObj) {
this.proxyObj = proxyObj;
Class<?> clazz = proxyObj.getClass();
// 创建动态代理
return GPProxy.newProxyInstance(new GPClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 数据源计算
before(args[0]);
// 调用原方法
Object object = method.invoke(proxyObj,args);
after();
return object;
}
// target 应该是订单对象Order
private void before(Object target) {
try {
// 进行数据源的切换
System.out.println("Proxy before method");
// 约定优于配置
Long time = (Long) target.getClass().getMethod("getCreateTime").invoke(target);
// 计算目标数据源编号
Integer dbRouter = Integer.valueOf(yearFormat.format(new Date(time)));
System.out.println("静态代理类自动分配到【DB_" + dbRouter + "】数据源处理数据");
}catch (Exception e){
e.printStackTrace();
}
}
private void after() {
System.out.println("Proxy after method");
}
}
本文标题:【设计模式】结构型:代理模式(二)JDK 动态代理
本文链接:https://blog.quwenai.cn/post/10203.html
版权声明:本文不使用任何协议授权,您可以任何形式自由转载或使用。






还没有评论,来说两句吧...