1.XML大臣
最近这几年,XML大臣的宅邸车水马龙,像什么Spring, Hibernate, MyBatis 等大大小小的官员进京来都要拜访一下,无数的冰敬碳敬悄悄地送入府中, 真可谓红极一时, 正处于人生***。 原因很简单,Java帝国的配置文件几乎都在使用XML, 自然都归XML大臣管理,想不红都难!
其他大臣看在眼里,恨在心里,他们决定联合起来,坚决打击XML大臣的嚣张气焰, 坚决把白花花的银子转移到自己府中来。 几位老家伙商量以后,决定还是推举老成持国的IO大臣为首领,给XML大臣一点颜色瞧瞧。
2.安翰林献计
可是IO大臣想了半天,也没什么好办法。
这一天有个姓安的翰林自报家门求见, 说是可以助IO大臣一臂之力。
“安大人有何见教?” IO大臣懒洋洋地问道,他对这些读死书的翰林们没什么好感。
“大人,下官在负责Java注解,对付XML大臣,也许是个突破口”
“注解? 这是什么东西?” IO大臣确实是有点老了
“其实就是元数据了”
“元数据?” IO大臣一头雾水。
“嗯, Metadata” 安翰林把英文都整出来了。
“卖它推它?” IO大臣明显英文不好。
旁边的幕僚一个劲儿的使眼色, 谆谆告诫安翰林要通俗易懂。
安翰林说: “大人肯定知道@Override,@SuppressWarning等注解吧? ”
IO大臣点头。
安翰林接着说: “所谓元数据, 就是描述数据的数据了,换句话说可以给其他数据提供描述性信息, 例如Java类中的某个方法,可以认为是一种数据, 如果我的@Override 一旦被用到这个方法上,那就意味着要覆盖父类/接口的方法了,于是我的@Override 就给这个方法提供了额外的信息。”
“但是在源代码中写个@Override 似乎也没什么用处啊? ” IO大臣问道
“所以这只是元数据, 它给其他数据(如Java方法)提供了信息, 但是怎么样利用这些信息那就不归我管了。”
“那归谁管?”
“比如@Override , 由编译器来管,当编译这个Java 文件的时候,它就会检查被@Override 修饰的方法是否和父类的方法和参数相同, 如果不同,就会报错了。”
IO大臣说: “奥,明白了,所谓的注解有点像加强版的注释, 这个“注释”不但有一定的格式,还有特定的含义,这样别的工具就可以读取它来做事情了!”
安翰林松了一口气, 心里暗自佩服IO大臣的总结能力。
“我记得这个@Override注解很早就有了啊,好像是JDK1.4吧”
“没错, 之前JDK内置了@Override、@Deprecated 、@SuppressWarnings等注解, 但是用处不大, 下官有个想法,干脆允许臣民们自定义注解得了” 安翰林开始切入正题。
“自定义? 就是让臣民们自己写? ”
“是的大人, 比如我可以自定义一个叫做 @Test的 注解:” 安翰林说着把写好的代码呈了上去。
安翰林接着说: 大人请看我这里定义了一个叫做Test的注解,它有个ignore方法, 一会儿您老就看到它的用途了, 这个注解是应用在方法上的 @Target(ElementType.METHOD), 在运行时起作用@Retention(RetentionPolicy.RUNTIME)。
IO大臣问道:“稍等, 我怎么还看到了@Target,@Retention, 这是什么? ”
“这称为元注解,可以认为是注解的注解。” 安翰林嘿嘿一笑说 “@Target表示该注解的应用目标,可以是类、方法、 方法参数等等, @Retention表示这个注解要保留到什么时候, 可以只在源码中, 或者class 文件中, 或者是运行时。”
“ 注解的注解, 真是够拗口的啊, 这个自定义的注解@Test 该怎么使用呢? ”
安翰林又展示了另外一段代码:
IO大臣看了下,心想这自定义的注解和JDK内置的注解都差不多嘛,@Test修饰了方法, 表示这个方法可以作为测试用例来运行, @Test(ignore=true)则表示虽然这是个测试方法, 但是暂时忽略,不用运行, 果然简洁而清爽,老夫真是小看了这个安翰林。
“@Test注解的定义和使用,只是定义了行为语义,怎么样实现这个行为呢? ” IO大臣问道
安翰林早有准备:“大人请看,我可以在运行时通过反射的方式取出把方法的注解,如果这个注解是@Test, 并且没有被ignore , 那就可以通过反射去执行这个方法了, 是不是很简单?”
IO大臣微微点了点头,表示赞同,接着便闭目陷入了沉思: 这个东西有点意思,在一个方法上添加了简单的修饰性注解@Test以后,这个方法突然间就有了额外的语义,变成了可以执行的测试用例了 !
如果是XML老头儿, 该怎么描述类似的行为呢? 也许得这样:
相比于简洁的@Test注解,这个方式实在是太复杂了, 更重要的是每次增加新的方法,除了修改Java文件之外,还得记着修改这个XML文件, 实在是繁琐。
嗯, 看来这个注解确实是个杀手锏, 要谨慎使用,一击必中。
想到这里,IO大臣睁开眼睛,喜笑颜开,让安翰林写一个关于注解的详细奏章,自己在合适的时候呈给皇上。
3.早朝争斗
初六阳光灿烂,IO大臣看到早朝的皇上心情不错,就把奏章呈了上去。
“注解? 这是什么东西?” 皇上根本没心思了解细节。
“启奏陛下,这个注解能够部分的代替一些XML的配置工作” IO大臣一边小心翼翼地回复,一边用余光向XML大臣扫去。
看到IO大臣向自己发难, XML大臣立刻警觉起来, 他马上说: “陛下,可否让老臣一观?”
皇帝示意让吕公公把奏章递给XML大臣。
XML大臣看了一会儿就明白大事不好, 这简直是釜底抽薪, 如果这个帝国批准了这个玩意儿,允许臣民们自定义注解,自己的势力要大大地被削弱了。
XML大臣脑海中出现一副可怕的场景, Spring, Struts, Hibernate 等纷纷倒戈,都采用注解来进行系统配置,白花花的银子开始流向IO大臣的府邸......
不, 坚决要把这点星星之火迅速扑灭。
“陛下,依老臣之见, 此法断不可行!” XML大臣斩钉截铁。
“为何不可行? 使用注解,配置靠近代码,容易阅读、容易修改!” IO大臣立刻反击, 为了展示易读易改,IO大臣还现场写了一段代码,描述了一个普通的Java 类是如何向数据库表和列映射的。 朝中多位大臣齐声喝彩, 为IO大臣摇旗呐喊。
“单独看一个当然很清晰, 但是如果多了, 配置分散在各个Java文件中, 极难查找,到时候你哭都来不及, 如果你用了XML, 所有的配置集中在一处, 一目了然。 还有,如果你想修改配置就得改Java源文件,重新编译部署,这也太扯了吧?!” XML大臣不甘示弱。
眼看着两位重臣开始剑拔弩张, 皇帝决定出面和稀泥, 他也不希望一家独大,也想平衡一下朝中关系。
“两位爱卿,依朕之意,还是先在JDK中加入自定义注解的支持,至于是用注解还是用XML, 还是让朕的子民们去选择吧! ”
看到皇上主意已定, 两位大臣只好退下。
自定义注解发布了, 令大家没有想到的是,无论是注解还是XML配置都没有占据垄断地位,很多人把二者混合起来使用了! 对于一些需要集中配置的场合,例如数据源的配置, 自然是用XML。 另外一方面对于@Controller, @RequestMapping, @Transactional 这样的注解 , 大家更喜欢和Java方法写在一起,显得简单而直观。
这正如朝中的局势,没人能够一家独大,XML大臣虽然丢失了一些领地,但依然是不可忽视的力量。 一场争斗,唯一的大赢家可能就是安翰林了,他被任命为Annotation大臣,专门管理自定义的注解。
【本文为51CTO专栏作者“刘欣”的原创稿件,转载请通过作者微信公众号coderising获取授权】