Начиная со 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 |
|
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ