This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Framework 7.0.6!spring-doc.cn

Using JSR-330 Standard Annotations

Spring offers support for JSR-330 standard Dependency Injection annotations which are available in the jakarta.inject package. These annotations may optionally be used as alternatives to Spring annotations.spring-doc.cn

To use them, you need to have the relevant jar in your classpath. For example, the jakarta.inject artifact is available in the standard Maven repository (repo.maven.apache.org/maven2/jakarta/inject/jakarta.inject-api/2.0.0/),spring-doc.cn

If you use Maven, you can add the following dependency to your pom.xml file.spring-doc.cn

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

Dependency Injection with @Inject and @Named

Instead of using @Autowired for dependency injection, you may optionally choose to use @jakarta.inject.Inject as follows.spring-doc.cn

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(...)
		// ...
	}
}

As with @Autowired, you can use @Inject at the field level, method level, and constructor-argument level.spring-doc.cn

Furthermore, as an alternative to Spring’s ObjectProvider mechanism, you may choose to declare your injection point as a jakarta.inject.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.spring-doc.cn

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
import jakarta.inject.Provider

class SimpleMovieLister {

	@Inject
	lateinit var movieFinder: Provider<MovieFinder>


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

If you would like to use a qualified name for the dependency that should be injected, you may choose to use the @Named annotation as an alternative to Spring’s @Qualifier support, as the following example shows.spring-doc.cn

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
	}

	// ...
}

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 examples show how to use @Inject with Optional, @Nullable, and Kotlin’s built-in support for nullable types.spring-doc.cn

import jakarta.inject.Inject;
import java.util.Optional;

public class SimpleMovieLister {

	@Inject
	public void setMovieFinder(Optional<MovieFinder> movieFinder) {
		// ...
	}
}
import jakarta.inject.Inject;
import org.jspecify.annotations.Nullable;

public class SimpleMovieLister {

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

class SimpleMovieLister {

	@Inject
	var movieFinder: MovieFinder? = null
}

@Named: Standard Equivalent to the @Component Annotation

Instead of @Component or other Spring stereotype annotations, you may optionally choose to use @jakarta.inject.Named, as the following example shows.spring-doc.cn

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

@Named("movieListener")
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")
class SimpleMovieLister {

	@Inject
	lateinit var movieFinder: MovieFinder

	// ...
}

It is very common to use @Component or other Spring stereotype annotations without specifying an explicit name for the component, and @Named can be used in a similar fashion, as the following example shows.spring-doc.cn

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

	// ...
}

When you use @Named, you can use component scanning in the exact same way as when you use Spring annotations, as the following example shows.spring-doc.cn

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
	// ...
}
@Configuration
@ComponentScan(basePackages = ["org.example"])
class AppConfig  {
	// ...
}
In contrast to @Component, the JSR-330 @Named annotation is not composable. You should use Spring’s stereotype model for building custom component annotations.

If you work with legacy systems that still use @javax.inject.Named or @javax.annotation.ManagedBean for components (note the javax package namespace), you can explicitly configure component scanning to include those annotation types, as shown in the following example.spring-doc.cn

@Configuration
@ComponentScan(
	basePackages = "org.example",
	includeFilters = @Filter({
		javax.inject.Named.class,
		javax.annotation.ManagedBean.class
	})
)
public class AppConfig  {
	// ...
}
@Configuration
@ComponentScan(
	basePackages = ["org.example"],
	includeFilters = [Filter([
		javax.inject.Named::class,
		javax.annotation.ManagedBean::class
	])]
)
class AppConfig  {
	// ...
}

In addition, if you would like for the value attributes in @javax.inject.Named and @javax.annotation.ManagedBean to be used as component names, you need to override the isStereotypeWithNameValue(…​) method in AnnotationBeanNameGenerator to add explicit support for javax.annotation.ManagedBean and javax.inject.Named and register your custom AnnotationBeanNameGenerator via the nameGenerator attribute in @ComponentScan.spring-doc.cn

Limitations of JSR-330 Standard Annotations

When you work with JSR-330 standard annotations, you should know that some significant features are not available, as the following table shows.spring-doc.cn

Table 1. Spring component model versus JSR-330 variants
Spring JSR-330 JSR-330 restrictions / comments

@Autowiredspring-doc.cn

@Injectspring-doc.cn

@Inject has no required attribute. Can be used with Java’s Optional instead.spring-doc.cn

@Componentspring-doc.cn

@Namedspring-doc.cn

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

@Scope("singleton")spring-doc.cn

@Singletonspring-doc.cn

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.spring-doc.cn

@Qualifierspring-doc.cn

@Qualifier / @Namedspring-doc.cn

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.spring-doc.cn

@Valuespring-doc.cn

-spring-doc.cn

no equivalentspring-doc.cn

@Lazyspring-doc.cn

-spring-doc.cn

no equivalentspring-doc.cn

ObjectFactoryspring-doc.cn

Providerspring-doc.cn

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.spring-doc.cn