动态代理和静态对比基本思路是一致的,只不过动态代理功能更加强大,随着业务的扩展适应性更强。如果还以找对象为例,使用动态代理相当于是能够适应复杂的业务场景。不仅仅只是父亲给儿子找对象,如果找对象这项业务发展成了一个产业,进而出现了媒婆、婚介所等这样的形式。那么,此时用静态代理成本就更大了,需要一个更加通用的解决方案,要满足任何单身人士找对象的需求。我们升级一下代码,先来看 JDK实现方式:
JDK实现方式
创建媒婆(婚介)JDKMeipo类:
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);
}
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 {
public void findLove(){
System.out.println("儿子要求:肤白貌美大长腿");
}
}
上面的案例理解了话,我们再来看数据源动态路由业务,帮助小伙伴们对动态代理加深一下印象。创建动态代理的类 OrderServiceDynamicProxy,代码如下:
public class OrderServiceDynamicProxy implements GPInvocationHandler {
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);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before(args[0]);
Object object = method.invoke(proxyObj,args);
after();
return object;
}
private void after() {
System.out.println("Proxy after method");
//还原成默认的数据源
DynamicDataSourceEntity.restore();
}
//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 + "】数据源处理数据");
DynamicDataSourceEntity.set(dbRouter);
}catch (Exception e){
e.printStackTrace();
}
}
}