pc|别再if-else走天下了,整个注解多优雅( 二 )


在OrderService中 , 维护了一个orderHandleMap , 它的key为订单来源 , value为对应的订单处理器Handler 。 通过@Autowired去初始化orderHandleMap(这里有一个lambda表达式 , 仔细看下其实没什么难度的) 。 这样一来 , OrderService.orderService里的一坨if-else不见了 , 取而代之的仅仅是两行代码 。 即 , 先从orderHandleMap中根据订单来源获取对应的OrderHandler , 然后执行OrderHandler.handle方法即可 。 这种做法的好处是 , 不论以后业务如何发展致使订单来源种类增加 , OrderService的核心逻辑不会改变 , 我们只需要实现新增来源的OrderHandler即可 , 且团队中每人开发各自负责的订单来源对应的OrderHandler即可 , 彼此间互不干扰 。
到此 , 似乎已经讲完了通过注解实现策略模式 , 干掉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启动参数如下: