Using JSR 330 Standard Annotations

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

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

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

  • Java

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

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

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

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

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

  // ...
}

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

public class SimpleMovieLister {

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

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

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

  • Java

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

  // ...
}

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

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

@Named
public class SimpleMovieLister {

  private MovieFinder movieFinder;

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

  // ...
}

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

  • Java

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
  // ...
}
In contrast to @Component, the JSR-330 @Named and the JSR-250 @ManagedBean annotations are not composable. You should use Infra 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. Infra component model elements versus JSR-330 variants
Infra 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 Infra prototype. However, in order to keep it consistent with Infra general defaults, a JSR-330 bean declared in the Infra container is a singleton by default. In order to use a scope other than singleton, you should use Infra @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 Infra @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 Infra ObjectFactory, only with a shorter get() method name. It can also be used in combination with Infra @Autowired or with non-annotated constructors and setter methods.