• 再谈Java,反射


    好像,是学过~

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

    他是谁呢?他就是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();
            }
        }
  • 相关阅读:
    error C2440: 'initializing' : cannot convert from 'const char [11]' to 'ATL::CStringT<BaseType,Strin
    DB1:数据库的创建和文件的修改
    Django之Form表单
    Django内置的分页模块
    Cookie和Session
    AJAX使用说明书 基础
    JSON和Django内置序列化
    django之urls系统
    Django之views系统
    模板语言
  • 原文地址:https://www.cnblogs.com/alipayhutu/p/2562856.html
Copyright © 2020-2023  润新知