使用 JSR 330 标准注解

Infra 支持 JSR-330 标准注解(依赖注入)。这些注解的扫描方式与 Infra 注解相同。 要使用它们,您需要在类路径中有相关的 jar。

如果您使用 Maven,jakarta.inject 工件在标准 Maven 存储库中可用 ( https://repo.maven.apache.org/maven2/jakarta/inject/jakarta.inject-api/2.0.0/). 您可以将以下依赖项添加到您的 pom.xml 文件中:

<dependency>
  <groupId>jakarta.inject</groupId>
  <artifactId>jakarta.inject-api</artifactId>
  <version>2.0.0</version>
</dependency>

使用 @Inject@Named 进行依赖注入

代替 @Autowired,您可以使用 @jakarta.inject.Inject,如下所示:

  • Java

import jakarta.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,允许按需访问较短作用域的 bean 或通过 Provider.get() 调用延迟访问其他 bean。 以下示例提供了前面示例的一个变体:

  • Java

import jakarta.inject.Inject;
import jakarta.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(...);
    // ...
  }
}

如果您想为应注入的依赖项使用限定名称,应使用 @Named 注解,如下例所示:

  • Java

import jakarta.inject.Inject;
import jakarta.inject.Named;

public class SimpleMovieLister {

  private MovieFinder movieFinder;

  @Inject
  public void setMovieFinder(@Named("main") MovieFinder movieFinder) {
    this.movieFinder = movieFinder;
  }

  // ...
}

@Autowired 一样,@Inject 也可以与 java.util.Optional@Nullable 一起使用。 这在这里甚至更适用,因为 @Inject 没有 required 属性。 以下一对示例显示了如何使用 @Inject@Nullable

public class SimpleMovieLister {

  @Inject
  public void setMovieFinder(Optional<MovieFinder> movieFinder) {
    // ...
  }
}
  • Java

public class SimpleMovieLister {

	@Inject
	public void setMovieFinder(@Nullable MovieFinder movieFinder) {
		// ...
	}
}

@Named@ManagedBean: @Component 注解的标准等效项

代替 @Component,您可以使用 @jakarta.inject.Namedjakarta.annotation.ManagedBean,如下例所示:

  • Java

import jakarta.inject.Inject;
import jakarta.inject.Named;

@Named("movieListener")  // 也可以使用 @ManagedBean("movieListener")
public class SimpleMovieLister {

  private MovieFinder movieFinder;

  @Inject
  public void setMovieFinder(MovieFinder movieFinder) {
    this.movieFinder = movieFinder;
  }

  // ...
}

使用 @Component 而不为组件指定名称是很常见的。@Named 可以以类似的方式使用,如下例所示:

  • Java

import jakarta.inject.Inject;
import jakarta.inject.Named;

@Named
public class SimpleMovieLister {

  private MovieFinder movieFinder;

  @Inject
  public void setMovieFinder(MovieFinder movieFinder) {
    this.movieFinder = movieFinder;
  }

  // ...
}

当您使用 @Named@ManagedBean 时,您可以像使用 Infra 注解一样使用组件扫描,如下例所示:

  • Java

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
  // ...
}
@Component 相比,JSR-330 @Named 和 JSR-250 @ManagedBean 注解不可组合。 您应该使用 Infra 原型模型来构建自定义组件注解。

JSR-330 标准注解的限制

当您使用标准注解时,您应该知道某些重要功能不可用,如下表所示:

Table 1. Infra 组件模型元素与 JSR-330 变体的比较
Infra jakarta.inject.* jakarta.inject 限制 / 备注

@Autowired

@Inject

@Inject 没有 'required' 属性。可以与 Java 8 的 Optional 一起使用。

@Component

@Named / @ManagedBean

JSR-330 不提供可组合模型,只提供识别命名组件的方法。

@Scope("singleton")

@Singleton

JSR-330 默认作用域类似于 Infra prototype。但是,为了与 Infra 一般默认值保持一致,在 Infra 容器中声明的 JSR-330 bean 默认为 singleton。 为了使用除 singleton 之外的作用域,您应该使用 Infra @Scope 注解。 jakarta.inject 还提供了一个 jakarta.inject.Scope 注解:但是,该注解仅用于创建自定义注解。

@Qualifier

@Qualifier / @Named

jakarta.inject.Qualifier 只是用于构建自定义限定符的元注解。 具体的 String 限定符(如带有值的 Infra @Qualifier)可以通过 jakarta.inject.Named 关联。

@Value

-

无等效项

@Lazy

-

无等效项

ObjectFactory

Provider

jakarta.inject.Provider 是 Infra ObjectFactory 的直接替代品,只是 get() 方法名称更短。 它还可以与 Infra @Autowired 结合使用,或者与未注解的构造函数和 setter 方法一起使用。