|
This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Framework 7.0.3! |
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.
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/),
|
If you use Maven, you can add the following dependency to your
|
Dependency Injection with @Inject and @Named
Instead of using @Autowired for dependency injection, you may optionally choose to 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(...)
// ...
}
}
As with @Autowired, you can use @Inject at the field level, method level, and
constructor-argument level.
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.
-
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
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.
-
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
}
// ...
}
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.
import jakarta.inject.Inject;
import java.util.Optional;
public class SimpleMovieLister {
@Inject
public void setMovieFinder(Optional<MovieFinder> movieFinder) {
// ...
}
}
-
Java
-
Kotlin
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.
-
Java
-
Kotlin
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.
-
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
// ...
}
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.
-
Java
-
Kotlin
@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
In addition, if you would like for the |
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 | JSR-330 | JSR-330 restrictions / comments |
|---|---|---|
|
|
|
|
|
JSR-330 does not provide a composable model, only a way to identify named components. |
|
|
The JSR-330 default scope is like Spring’s |
|
|
|
|
- |
no equivalent |
|
- |
no equivalent |
|
|
|