3.11 使用JSR 330标准注解 {#toc_1}

从Spring3.0开始,Spring提供了对JSR-330标准注解(依赖注入)的支持。这些注解和Spring的注解以相同的方式进行扫描。你只需要在你的classpath中添加有关的jar包。

如果你使用maven,javax.inject 存在标准的maven库中(http://repo1.maven.org/maven2/javax/inject/javax.inject/1/),你可以将下面的依赖加入到你的pom.xml:

  1. <dependency>
  2. <groupId>javax.inject</groupId>
  3. <artifactId>javax.inject</artifactId>
  4. <version>1</version>
  5. </dependency>

3.11.1 使用@Inject and @Named依赖注入 {#toc_2}

和@Autowired不同的是,@javax.inject.Inject的使用如下:

  1. import javax.inject.Inject;import javax.inject.Inject;
  2. public class SimpleMovieLister {
  3. private MovieFinder movieFinder;
  4. @Inject
  5. public void setMovieFinder(MovieFinder movieFinder) {
  6. this.movieFinder = movieFinder;
  7. }
  8. public void listMovies() {
  9. this.movieFinder.findMovies(...);
  10. ...
  11. }
  12. }

和@Autowired一样,@Inject被用在字段级别、方法级别和构造器参数级别。更进一步的讲,你可以把注入点声明为一个提供者,允许通过Provider.get()调用按需访问较短范围的bean或者延迟访问其他bean。上面例子的变形:

  1. private Provider<MovieFinder> movieFinder;
  2. import javax.inject.Inject;
  3. import javax.inject.Provider;
  4. public class SimpleMovieLister {
  5. @Inject
  6. public void setMovieFinder(Provider<MovieFinder> movieFinder) {
  7. this.movieFinder = movieFinder;
  8. }
  9. public void listMovies() {
  10. this.movieFinder.get().findMovies(...);
  11. ...
  12. }
  13. }

如果你需要使用限定名作为依赖的注入想,那么你应该使用@Named注解,如下所示:

  1. import javax.inject.Inject;
  2. import javax.inject.Named;
  3. public class SimpleMovieLister {
  4. private MovieFinder movieFinder;
  5. @Inject
  6. public void setMovieFinder(@Named("main") MovieFinder movieFinder) {
  7. this.movieFinder = movieFinder;
  8. }
  9. // ...
  10. }

3.11.2 和标准@Component注解等价@Named和@ManagedBean {#toc_3}

和@Component注解不同,@javax.inject.Named or javax.annotation.ManagedBean使用如下:

  1. import javax.inject.Inject;
  2. import javax.inject.Named;
  3. @Named("movieListener") // @ManagedBean("movieListener") could be used as well
  4. public class SimpleMovieLister {
  5. private MovieFinder movieFinder;
  6. @Inject
  7. public void setMovieFinder(MovieFinder movieFinder) {
  8. this.movieFinder = movieFinder;
  9. }
  10. // ...
  11. }

对于@Component而言不指定名称是非常常见的。@Named也可以使用类似的方式:

  1. import javax.inject.Inject;
  2. import javax.inject.Named;
  3. @Named
  4. public class SimpleMovieLister {
  5. private MovieFinder movieFinder;
  6. @Inject
  7. public void setMovieFinder(MovieFinder movieFinder) {
  8. this.movieFinder = movieFinder;
  9. }
  10. // ...
  11. }

当使用@Named或@ManagedBean时,可以与使用Spring注解以完全相同的方式扫描组件:

  1. @Configuration
  2. @ComponentScan(basePackages = "org.example")
  3. public class AppConfig {
  4. ...
  5. }

和@Component不同,the JSR-330 @Named注解和JSR-250 ManagedBean注解它们之间不能组合。请使用Spring的原型模式来构建自定义组件注解。

3.11.3 JSR-330标准注解的局限性 {#toc_4}

当你使用标准注解时,务必要知道一些重要的不可用的特性,如下表所示:

表3.6 Spring组件模型元素 vs JSR-330 变体

Spring javax.inject.* javax.inject restrictions / comments
@Autowired @Inject @Inject 没有’required’属性;可以使用Java 8 的Optional 代替
@Component @Named / @ManagedBean JSR-330 不提供组合模型,仅仅是识别组件命名的途径
@Scope(“singleton”) @Singleton JSR-330默认范围类似Spring的原型。但是,为了使其与Spring常规默认值保持一致,默认情况下,在Spring容器中声明的JSR-330 bean是单例。为了使用一个不是单例的范围,您应该使用Spring的@Scope注解。javax.inject还提供了@Scope注解。然而,这只是用于创建自己的注解。
@Qualifier @Qualifier / @Named javax.inject.Qualifier只是构建自定义限定符的元注解。具体的字符串限定符(像Spring的@Qualifier值)可以通过javax.inject.Named关联
@Value 没有对应的
@Required 没有对应的
@Lazy 没有对应的
ObjectFactory Provider javax.inject.Provider是Spring ObjectFactory 的替代品,只需要一个简短的get()方法名称。它也可以和Spring @Autowired或非注解的构造器和setter方法结合使用。