Spring @Autowired 가이드

1. 개요

Spring 2.5부터 프레임 워크는 주석 기반 종속성 주입을 도입했습니다 . 이 기능의 주요 주석은 @Autowired 입니다. 이를 통해 Spring은 협업 빈을 해결하고 빈에 주입 할 수 있습니다.

이 자습서에서는 먼저 자동 연결을 활성화하는 방법과여러빈을 autowire하는 방법. 나중에 @Qualifier 주석을 사용하여 빈 충돌을 해결하는 방법 과 잠재적 인 예외 시나리오에 대해 이야기하겠습니다 .

2. @Autowired 주석 활성화

Spring 프레임 워크는 자동 종속성 주입을 가능하게합니다. 즉, Spring 구성 파일에서 모든 Bean 종속성을 선언함으로써 Spring 컨테이너는 협업 Bean 간의 관계를 자동으로 연결할 수 있습니다 . 이것을 Spring bean autowiring 이라고 합니다.

애플리케이션에서 Java 기반 구성을 사용하기 위해 주석 기반 주입을 활성화하겠습니다.Spring 구성을로드하려면 :

@Configuration @ComponentScan("com.baeldung.autowire.sample") public class AppConfig {}

또는 주석은 주로 Spring XML 파일에서 종속성 주입 주석을 활성화하는 데 사용됩니다.

또한 Spring Boot는 @SpringBootApplication 주석을 도입합니다 . 이 단일 주석은 @Configuration , @EnableAutoConfiguration@ComponentScan 을 사용하는 것과 동일합니다 .

애플리케이션의 메인 클래스에서이 주석을 사용해 보겠습니다.

@SpringBootApplication class VehicleFactoryApplication { public static void main(String[] args) { SpringApplication.run(VehicleFactoryApplication.class, args); } }

결과적으로이 Spring Boot 애플리케이션을 실행 하면 현재 패키지와 하위 패키지의 구성 요소를 자동으로 스캔합니다 . 따라서 Spring의 Application Context에 등록하고 @Autowired를 사용하여 빈을 주입 할 수 있습니다.

3. @Autowired 사용

주석 주입을 활성화 한 후 속성, setter 및 생성자에서 자동 연결을 사용할 수 있습니다 .

3.1. @Autowired 속성

@Autowired를 사용하여 속성에 주석을 달 수있는 방법을 살펴 보겠습니다 . 이렇게하면 게터와 세터가 필요하지 않습니다.

먼저 fooFormatter 빈을 정의 해 보겠습니다 .

@Component("fooFormatter") public class FooFormatter { public String format() { return "foo"; } }

그런 다음 필드 정의에서 @Autowired 를 사용 하여이 빈을 FooService 빈에 주입합니다 .

@Component public class FooService { @Autowired private FooFormatter fooFormatter; }

결과적으로 Spring은 FooService 가 생성 될 때 fooFormatter를 주입 합니다.

3.2. 세터에서 @Autowired

이제 setter 메서드에 @Autowired 주석을 추가해 보겠습니다 .

다음 예제에서는 FooService 가 생성 될 때 FooFormatter 인스턴스와 함께 setter 메서드가 호출됩니다 .

public class FooService { private FooFormatter fooFormatter; @Autowired public void setFooFormatter(FooFormatter fooFormatter) { this.fooFormatter = fooFormatter; } } 

3.3. 생성자에서 @Autowired

마지막으로 생성자에서 @Autowired 를 사용합시다 .

FooFormatter 의 인스턴스가 FooService 생성자에 대한 인수로 Spring에 의해 주입되는 것을 볼 수 있습니다 .

public class FooService { private FooFormatter fooFormatter; @Autowired public FooService(FooFormatter fooFormatter) { this.fooFormatter = fooFormatter; } }

4. @Autowired 및 선택적 종속성

빈이 생성 될 때 @Autowired 종속성을 사용할 수 있어야합니다. 그렇지 않으면 Spring이 연결을 위해 Bean을 해결할 수 없으면 예외가 발생 합니다.

결과적으로 다음과 같은 형식을 제외하고는 Spring 컨테이너가 성공적으로 시작되는 것을 방지합니다.

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.autowire.sample.FooDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

이 문제를 해결하려면 필요한 유형의 빈을 선언해야합니다.

public class FooService { @Autowired(required = false) private FooDAO dataAccessor; }

5. Autowire 명확성

기본적으로 Spring 은 유형별 로 @Autowired 항목을 확인합니다. 컨테이너에서 동일한 유형의 Bean을 두 개 이상 사용할 수있는 경우 프레임 워크에서 치명적인 예외가 발생 합니다.

이 충돌을 해결하려면 주입 할 빈을 명시 적으로 Spring에 알려야합니다.

5.1. @Qualifier에 의한 자동 연결

예를 들어 @Qualifier 주석을 사용하여 필요한 빈을 표시하는 방법을 살펴 보겠습니다 .

먼저 Formatter 유형의 Bean 2 개를 정의합니다 .

@Component("fooFormatter") public class FooFormatter implements Formatter { public String format() { return "foo"; } }
@Component("barFormatter") public class BarFormatter implements Formatter { public String format() { return "bar"; } }

이제 FooService 클래스에 Formatter 빈 을 주입 해 보겠습니다 .

public class FooService { @Autowired private Formatter formatter; }

In our example, there are two concrete implementations of Formatter available for the Spring container. As a result, Spring will throw a NoUniqueBeanDefinitionException exception when constructing the FooService:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.autowire.sample.Formatter] is defined: expected single matching bean but found 2: barFormatter,fooFormatter 

We can avoid this by narrowing the implementation using a @Qualifier annotation:

public class FooService { @Autowired @Qualifier("fooFormatter") private Formatter formatter; }

When there are multiple beans of the same type, it's a good idea to use @Qualifier to avoid ambiguity.

Please note that the value of the @Qualifier annotation matches with the name declared in the @Component annotation of our FooFormatter implementation.

5.2. Autowiring by Custom Qualifier

Spring also allows us to create our own custom @Qualifier annotation. To do so, we should provide the @Qualifier annotation with the definition:

@Qualifier @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface FormatterType { String value(); }

Then we can use the FormatterType within various implementations to specify a custom value:

@FormatterType("Foo") @Component public class FooFormatter implements Formatter { public String format() { return "foo"; } }
@FormatterType("Bar") @Component public class BarFormatter implements Formatter { public String format() { return "bar"; } }

Finally, our custom Qualifier annotation is ready to use for autowiring:

@Component public class FooService { @Autowired @FormatterType("Foo") private Formatter formatter; } 

The value specified in the @Target meta-annotation restricts where to apply the qualifier, which in our example is fields, methods, types, and parameters.

5.3. Autowiring by Name

Spring uses the bean's name as a default qualifier value. It will inspect the container and look for a bean with the exact name as the property to autowire it.

Hence, in our example, Spring matches the fooFormatter property name to the FooFormatter implementation. Therefore, it injects that specific implementation when constructing FooService:

public class FooService { @Autowired private Formatter fooFormatter; }

6. Conclusion

In this article, we discussed autowiring and the different ways to use it. We also examined ways to solve two common autowiring exceptions caused by either a missing bean or an ambiguous bean injection.

The source code of this article is available on the GitHub project.