现在的位置: 首页 > 综合 > 正文

再谈Java,反射

2013年05月27日 ⁄ 综合 ⁄ 共 2879字 ⁄ 字号 评论关闭

好像,是学过~

眼下,却怎也想不起来可以用他~

他是谁呢?他就是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();

        }

    }

抱歉!评论已关闭.