Using @Autowired(한글)

이 섹션에 포함된 예제에서는 JSR 330의 @Inject 어노테이션을 Spring의 @Autowired 어노테이션 대신 사용할 수 있습니다. 자세한 내용은 여기를 참조하세요.

다음 예시와 같이 생성자에 @Autowired 어노테이션을 적용할 수 있습니다:

  • Java

  • Kotlin

public class MovieRecommender {

	private final CustomerPreferenceDao customerPreferenceDao;

	@Autowired
	public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
		this.customerPreferenceDao = customerPreferenceDao;
	}

	// ...
}
class MovieRecommender @Autowired constructor(
	private val customerPreferenceDao: CustomerPreferenceDao)

Spring 프레임워크 4.3부터, 대상 Bean이 처음부터 하나의 생성자만 정의하는 경우 이러한 생성자에 대한 @Autowired 어노테이션은 더 이상 필요하지 않습니다. 그러나 여러 생성자를 사용할 수 있고 주(primary)/기본(default) 생성자가 없는 경우 컨테이너에 어떤 생성자를 사용할지 지시하기 위해 생성자 중 하나 이상에 @Autowired 어노테이션을 추가해야 합니다. 자세한 내용은 생성자 해결책에 대한 설명을 참조하세요.

다음 예제에서 볼 수 있듯이 @Autowired 어노테이션을 전통적인 setter 메서드에 적용할 수도 있습니다:

  • Java

  • Kotlin

public class SimpleMovieLister {

	private MovieFinder movieFinder;

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

	// ...
}
class SimpleMovieLister {

	@set:Autowired
	lateinit var movieFinder: MovieFinder

	// ...

}

다음 예제에서 볼 수 있듯이 임의의 이름과 여러 인수가 있는 메서드에도 어노테이션을 적용할 수 있습니다:

  • Java

  • Kotlin

public class MovieRecommender {

	private MovieCatalog movieCatalog;

	private CustomerPreferenceDao customerPreferenceDao;

	@Autowired
	public void prepare(MovieCatalog movieCatalog,
			CustomerPreferenceDao customerPreferenceDao) {
		this.movieCatalog = movieCatalog;
		this.customerPreferenceDao = customerPreferenceDao;
	}

	// ...
}
class MovieRecommender {

	private lateinit var movieCatalog: MovieCatalog

	private lateinit var customerPreferenceDao: CustomerPreferenceDao

	@Autowired
	fun prepare(movieCatalog: MovieCatalog,
				customerPreferenceDao: CustomerPreferenceDao) {
		this.movieCatalog = movieCatalog
		this.customerPreferenceDao = customerPreferenceDao
	}

	// ...
}

다음 예시와 같이 필드에도 `@Autowired`를 적용할 수 있으며 생성자와 혼합하여 사용할 수도 있습니다:

  • Java

  • Kotlin

public class MovieRecommender {

	private final CustomerPreferenceDao customerPreferenceDao;

	@Autowired
	private MovieCatalog movieCatalog;

	@Autowired
	public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
		this.customerPreferenceDao = customerPreferenceDao;
	}

	// ...
}
class MovieRecommender @Autowired constructor(
	private val customerPreferenceDao: CustomerPreferenceDao) {

	@Autowired
	private lateinit var movieCatalog: MovieCatalog

	// ...
}

대상 컴포넌트(예: MovieCatalog 또는 CustomerPreferenceDao )가 @Autowired 주석이 달린 주입 지점에 사용하는 유형으로 일관되게 선언되어 있는지 확인하세요. 그렇지 않으면 런타임에 "일치하는 유형을 찾을 수 없음" 오류로 인해 주입이 실패할 수 있습니다.

클래스 경로 검색을 통해 찾은 XML 정의 Bean 또는 컴포넌트 클래스의 경우, 컨테이너는 일반적으로 구체적인 유형을 미리 알고 있습니다. 그러나 @Bean 팩토리 메서드의 경우, 선언된 반환 유형이 충분히 표현력이 있는지 확인해야 합니다. 여러 인터페이스를 구현하는 컴포넌트나 구현 유형에 의해 잠재적으로 참조될 수 있는 컴포넌트의 경우, 팩토리 메서드에 가장 구체적인 반환 유형을 선언하는 것을 고려하세요(최소한 Bean을 참조하는 주입 지점에서 요구하는 만큼 구체적이어야 합니다).

다음 예제와 같이 해당 유형의 배열을 기대하는 필드 또는 메서드에 @Autowired 어노테이션을 추가하여 ApplicationContext 에서 특정 유형의 모든 Bean을 제공하도록 Spring에 지시할 수도 있습니다:

  • Java

  • Kotlin

public class MovieRecommender {

	@Autowired
	private MovieCatalog[] movieCatalogs;

	// ...
}
class MovieRecommender {

	@Autowired
	private lateinit var movieCatalogs: Array<MovieCatalog>

	// ...
}

다음 예에서 볼 수 있듯이 입력된 컬렉션에도 동일하게 적용됩니다:

  • Java

  • Kotlin

public class MovieRecommender {

	private Set<MovieCatalog> movieCatalogs;

	@Autowired
	public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
		this.movieCatalogs = movieCatalogs;
	}

	// ...
}
class MovieRecommender {

	@Autowired
	lateinit var movieCatalogs: Set<MovieCatalog>

	// ...
}

배열 또는 목록의 항목이 특정 순서로 정렬되도록 하려면 대상 Bean이 org.springframework.core.Ordered 인터페이스를 구현하거나 @Order 또는 표준 @Priority 어노테이션을 사용할 수 있습니다. 그렇지 않으면 컨테이너에 있는 해당 대상 Bean 정의의 등록 순서를 따릅니다.

대상 클래스 수준과 @Bean 메서드에서 @Order 어노테이션을 선언할 수 있으며, 개별 Bean 정의(동일한 Bean 클래스를 사용하는 여러 정의의 경우)에 대해 선언할 수도 있습니다. @Order 값은 주입 지점의 우선순위에 영향을 미칠 수 있지만, 종속성 관계와 @DependsOn 선언에 의해 결정되는 싱글톤 시작 순서에는 영향을 미치지 않는다는 점에 유의하세요.

메서드에 선언할 수 없기 때문에 @Bean 수준에서는 표준 jakarta.annotation.Priority 어노테이션을 사용할 수 없다는 점에 유의하세요. 그 의미는 각 유형에 대해 단일 Bean에서 @Order 값과 @Primary 를 조합하여 모델링할 수 있습니다.

예상 키 유형이 String 인 한, Map 인스턴스도 자동 연결될 수 있습니다. 다음 예제에서 볼 수 있듯이 맵 값에는 예상 유형의 모든 Bean이 포함되고 키에는 해당 Bean 이름이 포함됩니다:

  • Java

  • Kotlin

public class MovieRecommender {

	private Map<String, MovieCatalog> movieCatalogs;

	@Autowired
	public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
		this.movieCatalogs = movieCatalogs;
	}

	// ...
}
class MovieRecommender {

	@Autowired
	lateinit var movieCatalogs: Map<String, MovieCatalog>

	// ...
}

기본적으로 지정된 주입 지점에 대해 일치하는 후보 Bean을 사용할 수 없는 경우 autowiring은 실패합니다. 선언된 배열, 컬렉션 또는 맵의 경우 일치하는 요소가 하나 이상 있을 것으로 예상됩니다.

기본 동작은 주석이 달린 메서드와 필드를 필수 종속성을 나타내는 것으로 처리하는 것입니다. 다음 예제에서 설명한 대로 이 동작을 변경하여 프레임워크가 충족되지 않는 주입 지점을 비필수(즉, @Autowiredrequired 속성을 false 로 설정)로 표시하여 건너뛸 수 있도록 설정할 수 있습니다:

  • Java

  • Kotlin

public class SimpleMovieLister {

	private MovieFinder movieFinder;

	@Autowired(required = false)
	public void setMovieFinder(MovieFinder movieFinder) {
		this.movieFinder = movieFinder;
	}

	// ...
}
class SimpleMovieLister {

	@Autowired(required = false)
	var movieFinder: MovieFinder? = null

	// ...
}

비필수 메서드는 종속성(또는 인수가 여러 개인 경우 종속성 중 하나)을 사용할 수 없는 경우 전혀 호출되지 않습니다. 이러한 경우 필수 필드가 아닌 필드는 전혀 채워지지 않고 기본값이 그대로 유지됩니다.

즉, 'required' 속성을 'false’로 설정하면 해당 속성이 autowiring을 위한 것이며, autowiring할 수 없는 경우_선택사항_ 해당 속성이 무시된다는 것을 나타냅니다. 이렇게 하면 종속성 주입을 통해 선택적으로 재정의할 수 있는 기본값을 프로퍼티에 할당할 수 있습니다.

주입된 생성자 및 팩토리 메서드 인수는 특별한 경우인데, 이는 잠재적으로 여러 생성자를 처리할 수 있는 Spring의 생성자 확인 알고리즘으로 인해 @Autowiredrequired 속성이 다소 다른 의미를 갖기 때문입니다. 생성자 및 팩토리 메서드 인수는 기본적으로 필수이지만 단일 생성자 시나리오에서는 다중 요소 주입 지점(배열, 컬렉션, 맵)이 일치하는 Bean이 없는 경우 빈 인스턴스로 해결되는 것과 같은 몇 가지 특수 규칙이 적용됩니다. 이를 통해 모든 종속성을 고유한 다중 인수 생성자에서 선언할 수 있는 일반적인 구현 패턴을 사용할 수 있습니다. - 예를 들어, @Autowired 어노테이션 없이 단일 공용 생성자로 선언할 수 있습니다.

주어진 Bean 클래스의 생성자 하나만 required 속성을 true 로 설정하여 @Autowired 를 선언할 수 있으며, 이는 Spring Bean으로 사용될 때 생성자를 autowiring으로 표시합니다. 결과적으로 required 속성을 기본값인 true 로 남겨두면 하나의 생성자만 @Autowired 로 주석을 달 수 있습니다. 여러 생성자가 어노테이션을 선언하는 경우, 모두 required=false 를 선언해야만 자동 와이어링 후보로 간주됩니다(XML의 autowire=constructor 와 유사). Spring 컨테이너에서 일치하는 Bean으로 충족할 수 있는 종속성 수가 가장 많은 생성자가 선택됩니다. 후보 중 어느 것도 만족할 수 없는 경우 주/기본 생성자(있는 경우)가 사용됩니다. 마찬가지로, 클래스가 여러 생성자를 선언하지만 @Autowired 로 주석을 달지 않은 경우 기본/기본 생성자(있는 경우)가 사용됩니다. 클래스가 처음부터 하나의 생성자만 선언하는 경우, 주석을 달지 않더라도 항상 이 생성자가 사용됩니다. 주석이 달린 생성자는 반드시 공개적일 필요는 없습니다.

또는 다음 예시와 같이 Java 8의 java.util.Optional 을 통해 특정 종속성의 비필수성을 표현할 수도 있습니다:

public class SimpleMovieLister {

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

Spring 프레임워크 5.0부터는 @Nullable 어노테이션(모든 패키지에서 모든 종류의 어노테이션을 사용할 수 있습니다. — 예: JSR-305의 javax.annotation.Nullable) 을 사용하거나 Kotlin에 내장된 널 안전 지원을 활용할 수도 있습니다:

  • Java

  • Kotlin

public class SimpleMovieLister {

	@Autowired
	public void setMovieFinder(@Nullable MovieFinder movieFinder) {
		...
	}
}
class SimpleMovieLister {

	@Autowired
	var movieFinder: MovieFinder? = null

	// ...
}

잘 알려진 해결 가능한 종속성인 인터페이스에는 @Autowired`를 사용할 수도 있습니다: BeanFactory, ApplicationContext, Environment, ResourceLoader, ApplicationEventPublisherMessageSource 와 같은 인터페이스에 대해서도 @Autowired 를 사용할 수 있습니다. 이러한 인터페이스와 그 확장 인터페이스(예: ConfigurableApplicationContext 또는 ResourcePatternResolver) 는 특별한 설정 없이도 자동으로 해결됩니다. 다음 예제는 ApplicationContext 객체를 자동 와이어링합니다:

  • Java

  • Kotlin

public class MovieRecommender {

	@Autowired
	private ApplicationContext context;

	public MovieRecommender() {
	}

	// ...
}
class MovieRecommender {

	@Autowired
	lateinit var context: ApplicationContext

	// ...
}

@Autowired, @Inject, @Value@Resource 어노테이션은 Spring BeanPostProcessor 구현에서 처리됩니다. 즉, 이러한 어노테이션은 자체 BeanPostProcessor 또는 BeanFactoryPostProcessor 유형(있는 경우) 내에서 적용할 수 없습니다. 이러한 유형은 XML 또는 Spring @Bean 메서드를 사용하여 명시적으로 '연결’해야 합니다.