[[beans-standard-annotations]]
= 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
(`https://repo.maven.apache.org/maven2/jakarta/inject/jakarta.inject-api/2.0.0/`),

[NOTE]
=====
If you use Maven, you can add the following dependency to your `pom.xml` file.

[source,xml,indent=0,subs="verbatim,quotes"]
----
	<dependency>
		<groupId>jakarta.inject</groupId>
		<artifactId>jakarta.inject-api</artifactId>
		<version>2.0.0</version>
	</dependency>
----
=====


[[beans-inject-named]]
== Dependency Injection with `@Inject` and `@Named`

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

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	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(...);
			// ...
		}
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	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.

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	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(...);
			// ...
		}
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	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.

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	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;
		}

		// ...
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	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.

[source,java,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	import jakarta.inject.Inject;
	import java.util.Optional;

	public class SimpleMovieLister {

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

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	import jakarta.inject.Inject;
	import org.jspecify.annotations.Nullable;

	public class SimpleMovieLister {

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

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	import jakarta.inject.Inject

	class SimpleMovieLister {

		@Inject
		var movieFinder: MovieFinder? = null
	}
----
======


[[beans-named]]
== `@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.

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	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;
		}

		// ...
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	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.

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	import jakarta.inject.Inject;
	import jakarta.inject.Named;

	@Named
	public class SimpleMovieLister {

		private MovieFinder movieFinder;

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

		// ...
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	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.

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	@Configuration
	@ComponentScan(basePackages = "org.example")
	public class AppConfig  {
		// ...
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	@Configuration
	@ComponentScan(basePackages = ["org.example"])
	class AppConfig  {
		// ...
	}
----
======

NOTE: In contrast to `@Component`, the JSR-330 `@Named` annotation is not composable. You
should use Spring's stereotype model for building custom component annotations.

[TIP]
====
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.

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	@Configuration
	@ComponentScan(
		basePackages = "org.example",
		includeFilters = @Filter({
			javax.inject.Named.class,
			javax.annotation.ManagedBean.class
		})
	)
	public class AppConfig  {
		// ...
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",fold="-imports"]
----
	@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`.
====


[[beans-standard-annotations-limitations]]
== 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.

[[annotations-comparison]]
.Spring component model versus JSR-330 variants
|===
| Spring | JSR-330 | JSR-330 restrictions / comments

| `@Autowired`
| `@Inject`
| `@Inject` has no `required` attribute. Can be used with Java's `Optional` instead.

| `@Component`
| `@Named`
| 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.
|===
