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:
<dependency><groupId>javax.inject</groupId><artifactId>javax.inject</artifactId><version>1</version></dependency>
3.11.1 使用@Inject and @Named依赖注入 {#toc_2}
和@Autowired不同的是,@javax.inject.Inject的使用如下:
import javax.inject.Inject;import javax.inject.Inject;public class SimpleMovieLister {private MovieFinder movieFinder;@Injectpublic void setMovieFinder(MovieFinder movieFinder) {this.movieFinder = movieFinder;}public void listMovies() {this.movieFinder.findMovies(...);...}}
和@Autowired一样,@Inject被用在字段级别、方法级别和构造器参数级别。更进一步的讲,你可以把注入点声明为一个提供者,允许通过Provider.get()调用按需访问较短范围的bean或者延迟访问其他bean。上面例子的变形:
private Provider<MovieFinder> movieFinder;import javax.inject.Inject;import javax.inject.Provider;public class SimpleMovieLister {@Injectpublic void setMovieFinder(Provider<MovieFinder> movieFinder) {this.movieFinder = movieFinder;}public void listMovies() {this.movieFinder.get().findMovies(...);...}}
如果你需要使用限定名作为依赖的注入想,那么你应该使用@Named注解,如下所示:
import javax.inject.Inject;import javax.inject.Named;public class SimpleMovieLister {private MovieFinder movieFinder;@Injectpublic void setMovieFinder(@Named("main") MovieFinder movieFinder) {this.movieFinder = movieFinder;}// ...}
3.11.2 和标准@Component注解等价@Named和@ManagedBean {#toc_3}
和@Component注解不同,@javax.inject.Named or javax.annotation.ManagedBean使用如下:
import javax.inject.Inject;import javax.inject.Named;@Named("movieListener") // @ManagedBean("movieListener") could be used as wellpublic class SimpleMovieLister {private MovieFinder movieFinder;@Injectpublic void setMovieFinder(MovieFinder movieFinder) {this.movieFinder = movieFinder;}// ...}
对于@Component而言不指定名称是非常常见的。@Named也可以使用类似的方式:
import javax.inject.Inject;import javax.inject.Named;@Namedpublic class SimpleMovieLister {private MovieFinder movieFinder;@Injectpublic void setMovieFinder(MovieFinder movieFinder) {this.movieFinder = movieFinder;}// ...}
当使用@Named或@ManagedBean时,可以与使用Spring注解以完全相同的方式扫描组件:
@Configuration@ComponentScan(basePackages = "org.example")public class AppConfig {...}
和@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方法结合使用。 |
