Using Jsr 330 Standard Annotations

Uso de anotaciones estándar JSR-330

Spring ofrece compatibilidad con las anotaciones estándar de inyección de dependencias JSR-330, disponibles en el paquete jakarta.inject. Estas anotaciones pueden utilizarse opcionalmente como alternativas a las anotaciones de Spring.

Para utilizarlas, debes tener el JAR correspondiente en el classpath. Por ejemplo, el artefacto jakarta.inject está disponible en el repositorio estándar de Maven. Si utilizas Maven, puedes añadir la siguiente dependencia a tu archivo pom.xml:

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

Inyección de dependencias con @Inject y @Named

En lugar de utilizar @Autowired para la inyección de dependencias, puedes optar por usar @jakarta.inject.Inject, como muestra el siguiente ejemplo:

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

Al igual que @Autowired, puedes utilizar @Inject en campos, métodos y argumentos de constructores.

Además, como alternativa al mecanismo ObjectProvider de Spring, puedes declarar el punto de inyección como jakarta.inject.Provider. Esto permite acceder bajo demanda a beans de ámbitos más cortos o acceder de forma diferida a otros beans mediante una llamada a Provider.get().

El siguiente ejemplo muestra una variante del anterior:

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

Si quieres utilizar un nombre calificado para la dependencia que se debe inyectar, puedes usar la anotación @Named como alternativa al soporte de @Qualifier de Spring:

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

	// ...
}

Al igual que @Autowired, @Inject también puede utilizarse con java.util.Optional o @Nullable. Esto es aún más relevante aquí, porque @Inject no tiene un atributo required.

El siguiente ejemplo muestra cómo utilizar @Inject con Optional:

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

public class SimpleMovieLister {

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

El siguiente ejemplo muestra cómo utilizar @Inject con @Nullable:

import jakarta.inject.Inject;
import org.jspecify.annotations.Nullable;

public class SimpleMovieLister {

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

@Named: equivalente estándar de la anotación @Component

En lugar de @Component u otras anotaciones estereotipo de Spring, puedes utilizar opcionalmente @jakarta.inject.Named, como muestra el siguiente ejemplo:

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

	// ...
}

Es muy habitual utilizar @Component u otras anotaciones estereotipo de Spring sin especificar un nombre explícito para el componente. @Named se puede utilizar de forma similar:

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

@Named
public class SimpleMovieLister {

	private MovieFinder movieFinder;

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

	// ...
}

Cuando utilizas @Named, puedes aplicar exploración de componentes exactamente de la misma manera que con las anotaciones de Spring:

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

A diferencia de @Component, la anotación JSR-330 @Named no es componible. Para crear anotaciones de componentes personalizadas, debes utilizar el modelo de anotaciones estereotipo de Spring.

Si trabajas con sistemas heredados que todavía utilizan @javax.inject.Named o @javax.annotation.ManagedBean para los componentes —ten en cuenta el espacio de nombres del paquete javax—, puedes configurar explícitamente la exploración de componentes para incluir esos tipos de anotación:

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

Además, si quieres que los atributos value de @javax.inject.Named y @javax.annotation.ManagedBean se utilicen como nombres de componentes, debes sobrescribir el método isStereotypeWithNameValue(…​) de AnnotationBeanNameGenerator para añadir compatibilidad explícita con javax.annotation.ManagedBean y javax.inject.Named.

Después, registra tu AnnotationBeanNameGenerator personalizado mediante el atributo nameGenerator de @ComponentScan.

Limitaciones de las anotaciones estándar JSR-330

Cuando trabajas con las anotaciones estándar JSR-330, debes tener en cuenta que algunas funcionalidades importantes no están disponibles, como muestra la siguiente tabla.

Spring JSR-330 Restricciones o comentarios de JSR-330
@Autowired @Inject @Inject no tiene atributo required. Puedes utilizar Optional de Java en su lugar.
@Component @Named JSR-330 no proporciona un modelo componible, solo una forma de identificar componentes con nombre.
@Scope("singleton") @Singleton El ámbito predeterminado de JSR-330 es similar al ámbito prototype de Spring. Sin embargo, para mantener la coherencia con los valores predeterminados generales de Spring, un bean JSR-330 declarado en el contenedor de Spring es singleton de forma predeterminada. Para utilizar un ámbito distinto de singleton, debes usar la anotación @Scope de Spring. jakarta.inject también proporciona la anotación jakarta.inject.Scope, pero está destinada únicamente a crear anotaciones personalizadas.
@Qualifier @Qualifier / @Named jakarta.inject.Qualifier es solo una meta-anotación para crear calificadores personalizados. Los calificadores concretos de tipo String —como @Qualifier de Spring con un valor— se pueden asociar mediante jakarta.inject.Named.
@Value No existe equivalente.
@Lazy No existe equivalente.
ObjectFactory Provider jakarta.inject.Provider es una alternativa directa a ObjectFactory de Spring, solo que con un nombre de método get() más corto. También puede utilizarse junto con @Autowired de Spring o con constructores y métodos setter sin anotaciones.