1.11. 使用JSR 330 标准注解
从Spring 3.0开始,Spring提供对JSR-330标准注解(依赖注入)的支持。 这些注解的扫描方式与Spring注解的扫描方式相同。 要使用它们,您需要在类路径中有相关的jar。
如果使用Maven,则标准Maven存储库(https://repo1.maven.org/maven2/javax/inject/javax.inject/1/)中提供了javax.inject组件。 您可以将以下依赖项添加到文件pom.xml中:
|
1.11.1. 依赖注入使用 @Inject
and @Named
代替@Autowired,你可以使用@javax.inject.Inject
如下:
java
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(...);
// ...
}
}
kotlin
import javax.inject.Inject
class SimpleMovieLister {
@Inject
lateinit var movieFinder: MovieFinder
fun listMovies() {
movieFinder.findMovies(...)
// ...
}
}
与@Autowired一样,您可以在字段级别,方法级别和构造函数参数级别使用@Inject。 此外,您可以将注入点声明为Provider,从而允许按需访问范围较小的bean,或者通过Provider.get()调用来延迟访问其他bean。 以下示例提供了前面示例的变体:
java
import javax.inject.Inject;
import javax.inject.Provider;
public class SimpleMovieLister {
private Provider<MovieFinder> movieFinder;
@Inject
public void setMovieFinder(Provider<MovieFinder> movieFinder) {
this.movieFinder = movieFinder;
}
public void listMovies() {
this.movieFinder.get().findMovies(...);
// ...
}
}
kotlin
import javax.inject.Inject
class SimpleMovieLister {
@Inject
lateinit var movieFinder: MovieFinder
fun listMovies() {
movieFinder.findMovies(...)
// ...
}
}
如果要为应注入的依赖项使用限定名称,则应使用@Named注解,如以下示例所示:
java
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;
}
// ...
}
kotlin
import javax.inject.Inject
import javax.inject.Named
class SimpleMovieLister {
private lateinit var movieFinder: MovieFinder
@Inject
fun setMovieFinder(@Named("main") movieFinder: MovieFinder) {
this.movieFinder = movieFinder
}
// ...
}
与@Autowired一样,@ Inject也可以与java.util.Optional或@Nullable一起使用。 这在这里更加适用,因为@Inject没有必需的属性。 以下一对示例显示了如何使用@Inject和@Nullable:
public class SimpleMovieLister {
@Inject
public void setMovieFinder(Optional<MovieFinder> movieFinder) {
// ...
}
}
java
public class SimpleMovieLister {
@Inject
public void setMovieFinder(@Nullable MovieFinder movieFinder) {
// ...
}
}
kotlin
class SimpleMovieLister {
@Inject
var movieFinder: MovieFinder? = null
}
1.11.2. @Named和@ManagedBean:与@Component注解标准相等
可以使用@ javax.inject.Named或javax.annotation.ManagedBean代替@Component,如以下示例所示:
java
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;
}
// ...
}
kotlin
import javax.inject.Inject
import javax.inject.Named
@Named("movieListener") // @ManagedBean("movieListener") could be used as well
class SimpleMovieLister {
@Inject
lateinit var movieFinder: MovieFinder
// ...
}
在不指定组件名称的情况下使用@Component是非常常见的。 可以类似的方式使用@Named,如以下示例所示:
java
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
kotlin
import javax.inject.Inject
import javax.inject.Named
@Named
class SimpleMovieLister {
@Inject
lateinit var movieFinder: MovieFinder
// ...
}
当使用@Named或@ManagedBean时,可以使用与使用Spring注解完全相同的方式来使用组件扫描,如以下示例所示:
java
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig {
// ...
}
kotlin
@Configuration
@ComponentScan(basePackages = ["org.example"])
class AppConfig {
// ...
}
与@Component相反,JSR-330 @Named和JSR-250 ManagedBean注解是不可组合的。 您应该使用Spring的构造型模型来构建自定义组件注解。 |
1.11.3. 标准的JSR-330注解的局限性
JSR-330的局限性使用标准注解时,您应该知道某些重要功能不可用,如下表所示:标准注解
Spring | javax.inject.* | javax.inject restrictions / comments |
---|---|---|
@Autowired | @Inject | @Inject没有'required'属性。 可以与Java 8的可选一起使用。 |
@Component | @Named / @ManagedBean | JSR-330不提供可组合的模型,仅提供一种识别命名组件的方法。 |
@Scope("singleton") | @Singleton | JSR-330的默认作用域类似于Spring的prototype。 但是,为了使它与Spring的常规默认设置保持一致,默认情况下,在Spring容器中声明的JSR-330 bean是一个单例。 为了使用singleton 作用域以外的作用域,您应该使用Spring的@Scope注解。 javax.inject还提供了@Scope注解。 但是,此仅用于创建自己的注解。 |
@Qualifier | @Qualifier / @Named | javax.inject.Qualifier只是用于构建自定义限定符的元注解。 可以通过javax.inject.Named关联具体的string限定词(例如带有值的Spring的@Qualifier)。 |
@Value | - | no equivalent |
@Required | - | no equivalent |
@Lazy | - | no equivalent |
ObjectFactory | Provider | javax.inject.Provider是Spring的ObjectFactory的直接替代品,只是具有较短的get()方法名称。 它也可以与Spring的@Autowired结合使用,也可以与无注解的构造函数和setter方法结合使用。 |