Using JSR 330 Standard Annotations

Spring 为 JSR-330 标准注解提供支持(依赖项注入)。这些注解的扫描方式与 Spring 注解相同。要使用它们,你需要在类路径中包含相关 jar。

Spring offers support for JSR-330 standard annotations (Dependency Injection). Those annotations are scanned in the same way as the Spring annotations. To use them, you need to have the relevant jars in your classpath.

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

If you use Maven, the jakarta.inject artifact is available in the standard Maven repository ( https://repo.maven.apache.org/maven2/jakarta/inject/jakarta.inject-api/2.0.0/). You can add the following dependency to your file pom.xml:

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

Dependency Injection with @Inject and @Named

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

Instead of @Autowired, you can use @jakarta.inject.Inject as follows:

  • Java

  • Kotlin

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

class SimpleMovieLister {

	@Inject
	lateinit var movieFinder: MovieFinder


	fun listMovies() {
		movieFinder.findMovies(...)
		// ...
	}
}

@Autowired 一样,你可以在字段级别、方法级别和构造函数参数级别使用 @Inject。此外,你可以将注入点声明为 Provider,允许按需访问较短作用域的 bean,或者通过 Provider.get() 调用来延迟访问其他 bean。以下示例提供了上述示例的一个变体:

As with @Autowired, you can use @Inject at the field level, method level and constructor-argument level. Furthermore, you may declare your injection point as a Provider, allowing for on-demand access to beans of shorter scopes or lazy access to other beans through a Provider.get() call. The following example offers a variant of the preceding example:

  • Java

  • Kotlin

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

class SimpleMovieLister {

	@Inject
	lateinit var movieFinder: Provider<MovieFinder>


	fun listMovies() {
		movieFinder.get().findMovies(...)
		// ...
	}
}

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

If you would like to use a qualified name for the dependency that should be injected, you should use the @Named annotation, as the following example shows:

  • Java

  • Kotlin

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;
	}

	// ...
}
import jakarta.inject.Inject
import jakarta.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 没有`required` 属性,所以在这种情况适用性更强。以下示例对展示如何使用 @Inject 和`@Nullable`:

As with @Autowired, @Inject can also be used with java.util.Optional or @Nullable. This is even more applicable here, since @Inject does not have a required attribute. The following pair of examples show how to use @Inject and @Nullable:

public class SimpleMovieLister {

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

  • Kotlin

public class SimpleMovieLister {

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

	@Inject
	var movieFinder: MovieFinder? = null
}

@Named and @ManagedBean: Standard Equivalents to the @Component Annotation

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

Instead of @Component, you can use @jakarta.inject.Named or jakarta.annotation.ManagedBean, as the following example shows:

  • Java

  • Kotlin

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

	// ...
}
import jakarta.inject.Inject
import jakarta.inject.Named

@Named("movieListener")  // @ManagedBean("movieListener") could be used as well
class SimpleMovieLister {

	@Inject
	lateinit var movieFinder: MovieFinder

	// ...
}

经常在不为组件指定名称的情况下使用 @Component@Named 可以以类似的方式使用,如下例所示:

It is very common to use @Component without specifying a name for the component. @Named can be used in a similar fashion, as the following example shows:

  • Java

  • Kotlin

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

@Named
public class SimpleMovieLister {

	private MovieFinder movieFinder;

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

	// ...
}
import jakarta.inject.Inject
import jakarta.inject.Named

@Named
class SimpleMovieLister {

	@Inject
	lateinit var movieFinder: MovieFinder

	// ...
}

使用 @Named@ManagedBean 时,可以与使用 Spring 注解时完全相同的方式使用组件扫描,如下例所示:

When you use @Named or @ManagedBean, you can use component scanning in the exact same way as when you use Spring annotations, as the following example shows:

  • Java

  • Kotlin

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
	// ...
}
@Configuration
@ComponentScan(basePackages = ["org.example"])
class AppConfig  {
	// ...
}

不同于`@Component`,JSR-330 `@Named`和JSR-250 `@ManagedBean`注解不可组合。您应该使用 Spring 的模式模型来构建自定义组件注解。

In contrast to @Component, the JSR-330 @Named and the JSR-250 @ManagedBean annotations are not composable. You should use Spring’s stereotype model for building custom component annotations.

Limitations of JSR-330 Standard Annotations

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

When you work with standard annotations, you should know that some significant features are not available, as the following table shows:

Table 1. Spring component model elements versus JSR-330 variants
Spring jakarta.inject.* jakarta.inject restrictions / comments

@Autowired

@Inject

@Inject has no 'required' attribute. Can be used with Java 8’s Optional instead.

@Component

@Named / @ManagedBean

JSR-330 does not provide a composable model, only a way to identify named components.

@Scope("singleton")

@Singleton

The JSR-330 default scope is like Spring’s prototype. However, in order to keep it consistent with Spring’s general defaults, a JSR-330 bean declared in the Spring container is a singleton by default. In order to use a scope other than singleton, you should use Spring’s @Scope annotation. jakarta.inject also provides a jakarta.inject.Scope annotation: however, this one is only intended to be used for creating custom annotations.

@Qualifier

@Qualifier / @Named

jakarta.inject.Qualifier is just a meta-annotation for building custom qualifiers. Concrete String qualifiers (like Spring’s @Qualifier with a value) can be associated through jakarta.inject.Named.

@Value

-

no equivalent

@Lazy

-

no equivalent

ObjectFactory

Provider

jakarta.inject.Provider is a direct alternative to Spring’s ObjectFactory, only with a shorter get() method name. It can also be used in combination with Spring’s @Autowired or with non-annotated constructors and setter methods.