Начиная со Spring 3.0, Spring предлагает поддержку аннотаций из JSR-330 (Внедрение зависимостей). Эти аннотации сканируются так же, как и аннотации Spring. Чтобы использовать их, вам необходимо иметь соответствующие jar-файлы в вашем пути классов.
Если вы используете Maven, артефакт javax.inject
находится в стандартном репозитории Maven ( https://repo1.maven.org/maven2/javax/inject/javax.inject/1/). Вы можете добавить следующую зависимость в свой файл pom.xml:
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
Внедрение зависимостей с помощью @Inject
и @Named
Вместо @Autowired
вы можете использовать @javax.inject.Inject
следующим образом:
import javax.inject.Inject;
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
public void listMovies() {
this.movieFinder.findMovies(...);
// ...
}
}
import javax.inject.Inject
class SimpleMovieLister {
@Inject
lateinit var movieFinder: MovieFinder
fun listMovies() {
movieFinder.findMovies(...)
// ...
}
}
Как и в случае с @Autowired
, вы можете использовать @Inject
на уровне поля, метода и аргумента конструктора. Более того, вы можете объявить свою точку внедрения как Provider
, что позволит получить доступ по требованию к бинам с более узкой областью видимости или отложенный доступ к другим бинам через вызов Provider.get()
. В следующем примере предложен вариант предыдущего примера:
import javax.inject.Inject;
import javax.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 javax.inject.Inject
class SimpleMovieLister {
@Inject
lateinit var movieFinder: Provider<MovieFinder>
fun listMovies() {
movieFinder.get().findMovies(...)
// ...
}
}
Если необходимо использовать полное имя для зависимости, которую нужно внедрить, вам потребуется использовать аннотацию @Named
, как показано в следующем примере:
import javax.inject.Inject;
import javax.inject.Named;
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(@Named("main") MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
import javax.inject.Inject
import javax.inject.Named
class SimpleMovieLister {
private lateinit var movieFinder: MovieFinder
@Inject
fun setMovieFinder(@Named("main") movieFinder: MovieFinder) {
this.movieFinder = movieFinder
}
// ...
}
Как и @Autowired
, @Inject
также можно использовать с java.util.Optional
или @Nullable
. Это тем более применимо в данном случае, поскольку @Inject
не имеет required
атрибута. Следующая пара примеров показывает, как использовать @Inject
и @Nullable
:
public class SimpleMovieLister {
@Inject
public void setMovieFinder(Optional<MovieFinder> movieFinder) {
// ...
}
}
public class SimpleMovieLister {
@Inject
public void setMovieFinder(@Nullable MovieFinder movieFinder) {
// ...
}
}
class SimpleMovieLister {
@Inject
var movieFinder: MovieFinder? = null
}
@Named
и @ManagedBean
: Стандартные эквиваленты аннотации @Component
Вместо @Component
можно использовать @javax.inject.Named
или javax.annotation.ManagedBean
, как показано в следующем примере:
import javax.inject.Inject;
import javax.inject.Named;
@Named("movieListener") // можно также использовать @ManagedBean("movieListener")
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
import javax.inject.Inject
import javax.inject.Named
@Named("movieListener") // можно также использовать @ManagedBean("movieListener")
class SimpleMovieLister {
@Inject
lateinit var movieFinder: MovieFinder
// ...
}
Очень часто используется @Component
без указания имени компонента. Аналогичным образом можно использовать @Named
, как показано в следующем примере:
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
import javax.inject.Inject
import javax.inject.Named
@Named
class SimpleMovieLister {
@Inject
lateinit var movieFinder: MovieFinder
// ...
}
Если вы задействуете @Named
или @ManagedBean
, то использовать сканирование компонентов можно точно так же, как и при использовании аннотаций Spring, как показано в следующем примере:
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig {
// ...
}
@Configuration
@ComponentScan(basePackages = ["org.example"])
class AppConfig {
// ...
}
@Component
, аннотации @Named
из JSR-330 и @ManagedBean
из JSR-250 не являются составными. Для создания специальных аннотаций компонентов следует использовать модель стереотипов Spring.Ограничения стандартных аннотаций JSR-330
При работе со стандартными аннотациями следует знать, что некоторые важные функции будут недоступны, как показано в следующей таблице:
Spring | javax.inject.* | ограничения/комментарии javax.inject |
---|---|---|
@Autowired |
@Inject |
У |
@Component |
@Named / @ManagedBean |
JSR-330 не предоставляет составную модель, только способ идентификации именованных компонентов. |
@Scope("singleton") |
@Singleton |
Область доступности по умолчанию из JSR-330 похожа на область доступности на уровне |
@Qualifier |
@Qualifier / @Named |
|
@Value |
- |
без эквивалента |
@Required |
- |
без эквивалента |
@Lazy |
- |
без эквивалента |
ObjectFactory |
Provider |
|