pc|别再if-else走天下了,整个注解多优雅( 二 )
到此 , 似乎已经讲完了通过注解实现策略模式 , 干掉if-else的方法 , 就这样结束了吗?不 , 真正的重点从现在才开始 。
现在回过头看orderHandleMap这个Map , 它的key是订单来源 , 假如 , 我们想通过订单来源+订单支付方式这两个属性来决定到底使用哪一种OrderHandler怎么办?比如PC端支付宝支付的订单是一种处理逻辑(PCAliPayOrderHandler) , PC端微信支付的订单是另外一种处理逻辑(PCWeChatOrderHandler) , 对应的还有移动端支付宝支付(MobileAliPayOrderHandler)和移动端微信支付(MobileWeChatOrderHandler) 。
这时候我们的key应该存什么呢 , 可能有人会说 , 我直接存订单来源+订单支付方式组成的字符串不就行了吗?确实可以 , 但是如果这时业务逻辑又变了(向pm低头) , PC端支付宝支付和微信支付是同一种处理逻辑 , 而移动端支付宝支付和微信支付是不同的处理逻辑 , 那情况就变成了PCAliPayOrderHandler和PCWeChatOrderHandler这两个类是同一套代码逻辑 。 我们干掉了if-else , 但却造出了两份相同的代码 , 这是一个作为有强迫症的程序员所不能容忍的 。 怎么干掉这两个逻辑相同的类呢?
首先 , 我们可以回顾下 , 注解它究竟是个什么玩意?不知道大家有没有注意到定义注解的语法 , 也就是@interface , 与定义接口的语法想比 , 仅仅多了一个@ 。 翻看jdk , 可以找到这么一个接口Annotation , 如下
/** * The common interface extended by all annotation types. Note that an * interface that manually extends this one does not define * an annotation type. Also note that this interface does not itself * define an annotation type. * * More information about annotation types can be found in section 9.6 of * The Java Language Specification. * * The {@link java.lang.reflect.AnnotatedElement} interface discusses * compatibility concerns when evolving an annotation type from being * non-repeatable to being repeatable. * * @author Josh Bloch * @since 1.5 */public interface Annotation { // …省略}
开头就表明了 , The common interface extended by all annotation types 。 说的很明白了 , 其实注解它就是个接口 , 对 , 它就是个接口而已 , @interface仅仅是个语法糖 。 那么 , 注解既然是个接口 , 就必然会有相应的实现类 , 那实现类哪里来呢?上述中我们仅仅定义了OrderHandlerType注解 , 别的什么也没有做 。 这时候不得不提动态代理了 , 一定是jdk在背后为我们做了些什么 。 为了追踪JVM在运行过程中生成的JDK动态代理类 。 我们可以设置VM启动参数如下:
-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true
该参数可以保存所生成的JDK动态代理类到本地 。 额外说一句 , 若我们想追踪cglib所生成的代理类 , 即对应的字节码文件 , 可以设置参数:
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "保存的路径")
添加参数后再次启动项目 , 可以看到我们项目里多了许多class文件(这里只截取了部分 , 笔者启动的项目共生成了97个动态代理类 。 由于我的项目是springboot环境 , 因此生成了许多如ConditionalOnMissingBean、Configuration、Autowired等注解对应的代理类):
本文插图
那接下来就是要找到我们所关心的 , 即jdk为我们自定义的OrderHandlerType注解所生成的代理类 。 由于jdk生成的动态代理类都会继承Proxy这个类 , 而java又是单继承的 , 所以 , 我们只需要找到实现了OrderHandlerType的类即可 。 遍历这些类文件 , 发现$Proxy63.class实现了我们定义的OrderHandlerType注解:
- 游人|别再摘了!中华民族园的景观农作物都“秃顶”了
- 儿童饮食|妈妈们别再给宝宝瞎补钙啦!这些症状未必都跟缺钙有关
- 冷无情|杨幂:你别再卖惨了!
- 超兽武装|千面英雄改名英雄觉醒,超兽武装回来了,希望蓝弧别再放鸽子了
- 冷暴力:“冷暴力”处理方式,正在摧毁多少家庭幸福?别再伤害最爱你的人
- 衬衣|蒋欣可别再胖下去了,穿蓝色条纹衬衣造型大翻车,全靠气质撑着
- 美剧去哪看|有肚子的女人别再“塞衣角”啦,学日本杂志这样穿,时髦还气质
- 穿搭|烂大街的凉鞋别再穿了 !今夏流行这4双“鞋子”,舒适时髦还百搭
- 青年|绿头苍蝇“以下犯上”,叼走天帝的皇冠,试图自称为王!
- 钟晓芹■钟晓芹请立刻马上和养鱼的复婚吧,你俩都别再祸害其他人了