论坛首页 Java版 Spring

Not Convinced about JavaConfig

浏览 15613 次
该帖已经被评为精华帖
作者 正文
时间:2007-11-10
印象中,Spring就象上个世纪的产品。不论使用方便性和代码设计都相当20世纪。有了Guice,Spring似乎应该逐渐退隐,被遗忘于江湖了。我最近这个项目就是在从Spring往Guice移植。大家都很高兴终于不用在这个即将失事的火车上挤着了。一个哥们在白板上用红笔大字写上:“用xml写配制半点好处也木有!”。

然后就看到了Spring JavaConfig。和这个火药贴:
http://www.jroller.com/habuma/entry/guice_vs_spring_javaconfig_a

本来都对Spring失去兴趣了,不过看这么多人为之正名,于是就去看了一下。总的来说呢,眼睛一亮,然后比较失望。

JavaConfig从语法上说比Guice 1.0又进了一步,使用了最简单直观的method,然后用一些annotation来增加功能。这个和Guice 2.0比较象。谁抄谁我不管,技术上就这么点东西,这年头,民工都快能造原子弹了。

简单的东西两者差不多。文章里比的是Guice 1.0, 但是我觉得拿快出来的Guice 2.0比较更加有意义一些。比如他那个KnightConfig的例子,用Guice 2.0写,大致是这样:

public class KnightModule {
  @Provide
  public Knight knight() {
    ...
  }

  @Provide
  public Quest quest() {
    ...
  }

  ...
}


JavaConfig是这样:
@Configuration
public class KnightConfig {
  @Bean public Knight knight() {
    KnightOfTheRoundTable knight = new KnightOfTheRoundTable("Bedivere");
    knight.setQuest(quest());
    return knight;
  }

  @Bean public Quest quest() {
     return new HolyGrailQuest();
  }

  @Bean @SpringAdvice("execution(* *.embarkOnQuest(..))")
  public MinstrelInterceptor minstelAdvice() {
     return new MinstrelInterceptor();
  }
}


除了annotation不同,都一样。JavaConfig基本上就是把xml的manual wiring换到Java里面了(一件非常积德的事情)。Walls喋喋不休地强调的Spring的非侵入性其实没半点意义。要是真不想用Guice的@Inject,你完全可以也写成这种manual wiring的形式(就象上面的例子一样),根本不会有侵入。Guice只不过是通过@Inject让你可以以少许的侵入换取编程的方便罢了。

我认为比较重要的,是两者如何解决“依赖”。这个骑士的例子不存在依赖,每个bean都不需要引用其它的bean。其实这种简单的例子根本就没有意义。你说你能看出来JavaConfig比直接用裸Java配制优势在哪?就在于你最后可以用:
Knight knight = (Knight) ctxt.getBean("knight");

而不是简单的:
Knight knight = new KnightModule().knight();

显得比较sophisticated?今天我“春”了?

然后我就去找了JavaConfig的教程,看了一下它怎么解决依赖,下面是例子:
@Bean(scope = DefaultScopes.SINGLETON)
public Person rod() {
  return new Person("Rod Johnson");
}

@Bean(scope = DefaultScopes.PROTOTYPE)
public Book book() {
  Book book = new Book("Expert One-on-One J2EE Design and Development");
  book.setAuthor(rod());  // rod() method is actually a bean reference !
  return book;
}


然后我就怅然太息。这就是Spring的想象力呀。还是xml那一套,不过是从:
<property name="author" ref="rod"/>

变成了
book.setAuthor(rod());


这到也罢了。但是看到人家自豪的宣称:“你以为rod()是个函数调用吗?哈,答错啦!扣10分。这其实是一个bean reference, 它不直接调用你简单的大脑自以为调用的rod()函数,也不要以为你在电脑前作弊,用F3/F4热键带你过去的就是正确的选项。正确的答案是这里通过Spring的魔法得到了一个singleton!强吧?”,我就吐了。

这里的魔术,不用说,又是用了cglib,给偷偷弄了一个子类给override了——虽然我看不见这个子类。
但是,用了cglib,也就意味着下面几个限制:
1. 必须有public default constructor。
2. 必须不能final
也就是说我这个Config类不能带状态,不能给它注射依赖。这些函数虽然不能是static(否则spring的魔法就失效了)但是作用跟static method一样。白马非马吗?

确实强悍啊。看来以后可以象oracle认证一样,弄个spring认证来骗钱好了。

算了,不够聪明的我还是看看Guice 2.0的吧:

@Provide @Singleton
public Person bob() {
  return new Person("crazybob");
}

@Provide
public Book book(Person author) {
  Book book = new Book("Guice!");
  book.setAuthor(author);
  return book;
}


恩。我发现我虽然比较笨,看这个代码似乎还没有什么困难。不过是两个一点花头没有的函数,我眼睛里看见的它做了什么,它就必然做了什么,所有经典物理定律完全适用,没有任何不符合常识的东西。而且这似乎更符合"don't call us, we'll call you"的精神。也不需要担心那么多限制。比如,我可以快乐地把book title当成参数注射到这个Module里面:
class BookModule {
  private final String title;

  BookModule(String title) {
    this.title = title;
  }

  @Provide @Singleton
  public Person bob() {
    return new Person("crazybob");
  }

  @Provide
  public Book book(Person author) {
    Book book = new Book(title);
    book.setAuthor(author);
    return book;
  }
}


想怎么搞就怎么搞,因为BookModule自己也不过就是一个没什么限制的Pojo。
   
时间:2007-11-10
坚持xml,为了config让java类贴很多的膏药代码,道德败坏阿
   
0 请登录后投票
时间:2007-11-10
比较笨,没看懂最后那段代码(把book title当成参数注射到这个Module里面)有什么比用Spring要快乐一些?ajoo能否再解说一下?
   
0 请登录后投票
时间:2007-11-10
movingboy 写道
比较笨,没看懂最后那段代码(把book title当成参数注射到这个Module里面)有什么比用Spring要快乐一些?ajoo能否再解说一下?

Guice 2.0还没出来。一切只是我的乐观预测(因为,如果需要,我自己也可以在Guice 1.0外围写这么一个分析annotation来自动生成Module的东西)。

比如:

String title = ...;
Module module = Modules.createProviderModule(new BookModule(title));
Injector injector = Guice.createInjector(module);
Book book = injector.getInstance(Book.class);


用JavaConfig,可能只能如此:
ApplicationContext ctxt = new JavaConfigContext(BookConfig.class);
// 没办法往BookConfig.class里面注射。
Book book = (Book) ctxt.getBean("book");
   
0 请登录后投票
时间:2007-11-11
the comparison doesn't make any sense
   
0 请登录后投票
时间:2007-11-11
用annotation写配置又比xml好在哪里?我也没看出来,总的来说,我感觉全局的配置用xml来做比较好,一些细粒度的针对单个类或者方法的配置用annotation比较好,所以比较理想的状况是两者结合起来使用,完全没有必要把它们对立起来。
   
0 请登录后投票
时间:2007-11-11
感觉用xml也是优于annotation。 比较同意 cppasm 说的。 像那些Service Dao定义的话, 觉得定义在一个xml中更直观。
   
0 请登录后投票
时间:2007-11-11
我就象在街道网贴Hibernate vs. Toplink 一样的无助啊。走错门儿了。
   
0 请登录后投票
时间:2007-11-12
为什么xml就不好呢? 同问
   
0 请登录后投票
时间:2007-11-12
思维的习惯问题?我倒是觉得XML可以以一种更友好的图形化的方式展现,并且是可以运行期动态调整的。
   
0 请登录后投票
论坛首页 Java版 Spring

跳转论坛:
JavaEye推荐