JSR 330 표준 어노테이션 사용하기
스프링 3.0부터 JSR-330 표준 어노테이션(의존성 주입)을 지원하기 시작합니다.
이 어노테이션은 스프링 어노테이션과 동일한 방식으로 탐지됩니다.
이것을 사용하려면 클래스패스에 맞는 JAR를 추가하시면 됩니다.
Info
메이븐을 사용한다면 표준 메이븐 리포지토리(https://repo1.maven.org/maven2/javax/inject/javax.inject/1/)에서 javax.inject
라는 아티펙트가 제공됩니다.
pom.xml 파일에 아래의 의존성을 추가하면 됩니다.
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
@Inject
와 @Named
를 사용한 의존성 주입
1.11.1. @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
import javax.inject.Provider
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
어노테이션과 동등한 표준
1.11.2. @Component
대신, 아래 예제에서 보여주는 것처럼 @javax.inject.Named
나 @javax.annotation.ManagedBean
을 사용하면 됩니다.
import javax.inject.Inject;
import javax.inject.Named;
@Named("movieLister") // @ManagedBean("movieLister") 도 가능합니다.
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
import javax.inject.Inject
import javax.inject.Named
@Named("movieLister") // @ManagedBean("movieLister") 도 가능합니다.
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
을 사용할 때 아래 예제에서 보여주는 것처럼 스프링 어노테이션과 같이 동일한 방법으로 컴포넌트 탐색이 가능합니다.
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig {
// ...
}
@Configuration
@ComponentScan(basePackages = ["org.example"])
class AppConfig {
// ...
}
Info
@Component
와 다르게 JSR-330 @Named
와 JSR-250 @ManagedBean
어노테이션은 조합이 불가능합니다.
따라서 사용자정의 컴포넌트 어노테이션 빌드하려면 스프링 스테레오타입 모델을 사용해야 합니다.
1.11.3. JSR-330 표준 어노테이션의 제한점
표준 어노테이션으로 작업할 때 아래 표와 같이 일부 중요한 기능이 사용불가능합니다.
스프링 컴포넌트 모델 요소 vs JSR-330
스프링 | javax.inject.* | 제한 및 비고 |
---|---|---|
@Autowired | @Inject | @Inject 는 required 속성이 없습니다. 자바 8의 Optional 을 대신 사용하면 됩니다. |
@Component | @Named / @ManagedBean | JSR-330은 조합구성을 제공하지 않기 때문에 명명된 컴포넌트만 식별해야 합니다. |
@Scope("singleton") | @Singleton | JSR-330의 기본범위는 스프링의 prototype 같습니다. 그러나 스프링의 일반 기본값과 일관성을 유지하기 위해 스프링 컨테이너에 선언된 JSR-330 빈은 기본적으로 싱글톤입니다. singleton 이 아닌 다른 범위를 사용하려면 스프링의 @Scope 어노테이션을 사용해야 합니다. javax.inject 도 @Scope 어노테이션을 제공합니다. 그럼에도 불구하고 이것은 자체적 어노테이션을 생성할 때 사용하기 위한 것 입니다. |
@Qualifier | @Qualifier / @Named | javax.inject.Qualifier 는 사용자정의 한정자를 만들기 위한 메타 어노테이션 입니다. 구체적인 String 으로 된 한정자(스프링의 값이 있는 @Qualifier 같은)는 javax.inject.Named 로 연결할 수 있습니다. |
@Value | - | 동등한 것이 없음 |
@Required | - | 동등한 것이 없음 |
@Lazy | - | 동등한 것이 없음 |
ObjectFactory | Provider | javax.inject.Provider 는 짧은 get() 함수명만 있는 스프링의 ObjectFactory 의 직접적 대안이 됩니다. 스프링의 @Autowired , 어노테이션이 없는 생성자나 Setter 함수와 조합하여 사용될 수 있습니다. |