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;
@Inject
public 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 {
@Inject
public 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;
@Inject
public 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 well
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
对于@Component而言不指定名称是非常常见的。@Named也可以使用类似的方式:
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public 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方法结合使用。 |