Java 的一些 black magic

Java 和 C++ 虽然都是 strong-typed language,但是有不少事情 C++ 做起来很麻烦而 Java 比较容易,这自然得益于 Java 的一些 black magic。

reflection

JVM 提供的 reflection 使得我们可以检阅任意对象的类型、方法、成员,乃至利用 reflection 调用这些东西,而 C++ 除了 RTTI 是原生的动态类型检查以外,没有任何语言或者标准库级别的支持,前面讨论过 boost.reflect 可以部分解决这些问题,但是我们并没有一些可供操纵的对象来获得任意类的信息,除非我们主动的注册。这也导致不少动态语言对应的 C/C++ 的 extension 我们需要通过一些 static 的结构注册这些方法。

与 reflection 相关的一些神奇的事情包括

  • 通过 annotation 为类添加一些附加的信息,例如 JUnit 的测试方面的信息,spring 关于 injection 的信息,hibernate 关于 model 约束、关系等相关信息
  • 可以通过 instrospection 设置属性,例如 apache beanutils、spring 通过 XML 设置属性等
  • IoC container,例如 spring 可以通过类型构造 bean,并将其互相关联起来

proxy

其实 Java 提供的 proxy 有点基于 reflection 的概念,通常只需要给一个 class/interface 的类对象就能初始化一个所谓的 proxy,它能够捕获这些类或接口的方法,并让用户决定在这些时候 proxy 的行为。这个看起来很简单的东西在 C++ 里面却很难模仿,

  • 通过 proxy 可以构造 mock(如 mockito),这可以在需要的地方动态的产生 mock/stub 供测试使用;
  • 方便实现 decorator pattern,许多的 decorator 本质上只是在外面包裹一层,如 logging、metric collection、exception handling、transaction 等资源的处理,这就导致了 runtime AOP、很多 service chain 里面的 handler、interceptor、validator,好处不用说,如果使用 C++ 多半要用静态的方式组装。

当然可能你觉得使用 reflection、proxy 可能会降低运行效率,实际上他们某些应用的确可以通过另外的方式来解决避免运行时的开销。

bytecode manipulation

这个终极武器莫过于直接在 bytecode level 的处理,通过 annotation 的标记或者另外的语法,你可以为

  • 某些成员增加 getter/setter
  • 提供 compile-time weaving、load-time weaving 的 AOP

这个典型的库就是 CGLib,它被 spring、hibernate 广泛的应用,比如 lombok 可以让你编译某些 code(带有 annotation)产生对应的 setter/getter、toString、equals 等方法,避免 boilerplate,aspectj 实现了几种简单的 AOP 的接口。

这些东西似乎 C++ 的世界里面都没有一些 production ready 的 solution 比较可惜。

——————-
And Jacob did so, and fulfilled her week: and he gave him Rachel his daughter to wife also.

Advertisements
Java 的一些 black magic

一个有关“Java 的一些 black magic”的想法

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s