好像,是学过~
眼下,却怎也想不起来可以用他~
他是谁呢?他就是Java reflect.
【背景描述】
A的运行,依赖于B框架,还依赖了C jar包。其中,B、C皆为基础jar包,为众多系统使用,但相互间无必然联系。
有一天,A提出一个需求,要在dev下,同一线程当中,需要B、C共享一些资源,如某些变量。
从实现上来讲,B、C就必须打通,即要相互依赖彼此。
【万分纠结】
这时候B、C就头痛了。B作为框架jar包,自是不能依赖于任何一个小小的上层jar包,而C作为通用的上层jar包,不止适用于B框架,对于UVW框架,也都是要适用的,也断然不可依赖B。
那么,应该怎么办呢?
【方案】
好了,开始想办法。
方法一
描述:A反正已经依赖了B,也依赖了C,那么就干脆由A做二者的调停者,即C提供出回调接口,让A调B,然后在必要的时候回调C。
优势:B、C之间保持独立,升级也相对方便。(一旦扯上关系,升级起来就“扯”了)
劣势:A需要改代码,这是他最不愿意做的事情。(1)A可能代表着很多个系统,一改则全都要改,不现实;(2)这个功能仅在dev下使用,如果改了代码,线上就也得这么着run,这是最不希望看到的。(3)这段代码,与A具体的业务逻辑半毛钱关系都没有,硬生生的放在那儿,好生奇怪。
方法二
描述:C稍微妥协一下,也不引入B的jar包,而只是用“reflect”来具体引用B提供的类及方法。同时需要加两处开关,(1) 环境开关,仍由B提供(B是框架嘛,自然做滴要多一点),(2)reflect来找这个类的这个方法,如果调不到,那就是A系统没有配置,暂时不启用这个功能,还是可以照run。完美,兼容。有些约束条件:
- B提供的类名、方法名、必要的几个参数的类型,不许变;
- 静态类,静态方法;(因为没必要设计成为单例或pojo对象,不需要维护什么属性状态值,只需将B、C共享的那一部分资源,放到线程的threadlocal当中就行了,B提供get/set方法给C用即可,如此便“通”也)
- B类依赖的其他类(import),必须全都具备,这样C通过reflect方式调用才可能成功;
优势:没有明显jar包依赖,B、C基本做到了依然的“我行我素”,保持了自身的清白。
劣势:把B的类、方法、类形式,显式的限死了,绝对不能改,改了的后果就是那个功能不生效了,这样也算硬编码了吧?还是不够优雅。
方法三…
其实,蹩脚的方法我还想了很多种,这里不再一一列举,哪位大侠路过,有没有好的意见建议呢?
【扩展】
下次,这些个情况,我得想起reflect:
再忘,就罚自己吃一桶冰淇淋!!!
(1)reflect是解除依赖的好办法,无论是系统间,还是系统内部上、下层间。编译时不care,运行时才care。
(2)用于某些模块集成场合。例如,当你不能在开发时即得到其目标类完整接口定义,只能根据命名规则去进行集成时。
(3)可以延伸到包装、动态代理等模式的应用中。
(4)有时候也干些hack的事情,比如绕过private保护机制啥的。
(5)较底层的代码,reflect用的比较多,例如Spring, SSH框架的实现。
反射,却也引入了一定的不优雅:类名、方法、参数类型,均不得变。
http://wenku.baidu.com/view/1cd6aa8302d276a200292eed.html
http://www.cnblogs.com/alipayhutu/archive/2012/04/09/2439499.html
【代码demo】
public class Main {
/** 统一上下文类名 */
private String CLASS_NAME = "com.hutu.reflect.UniformedContextManager";
/** 获取统一上下文的方法名 */
private String GET_METHOD_NAME = "checkExit";
/** 设置统一上下文的方法名 */
private String SET_METHOD_NAME = "checkEntrance";
private Method getContextMethod = null;
private Method setContextMethod = null;
/**
* 构造函数.
*/
public Main() throws Exception{
Class<?> classType = Class.forName(CLASS_NAME);
// checkExit(String id, String ...other),注意第2个参数
this.getContextMethod = classType.getMethod(GET_METHOD_NAME, new Class[] { String.class, String[].class });
// checkEntrance(Object obj)
this.setContextMethod = classType.getMethod(SET_METHOD_NAME, Object.class);
}
/**
* 该方法获取统一上下文.
*
* @param message
* @return
*/
public byte[] getUniformedContext(Message message){
byte[] result = null;
if(this.getContextMethod == null){
return result;
}
try {
// 静态方法
Object projInfo = getContextMethod.invoke(null, new Object[] { message.getMessageId(), null});
result = projInfo.toString().getBytes();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 调用该方法设置统一上下文.
*
* @param message
*/
public void setUniformedContext(Message message){
if(null == this.setContextMethod || null == message){
return ;
}
try {
// 静态方法,注意参数的写法,不能写作:null或new Object[]{}
setContextMethod.invoke(null, new Object[]{null});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 主函数入口.
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
try{
Main o = new Main();
o.getUniformedContext(new Message());
o.setUniformedContext(new Message());
}catch(Exception e){
e.printStackTrace();
}
}