Spring @Autowired 사용법 이해


309

Spring Autowired 주석을 이해하기 위해 spring 3.0.x 참조 문서를 읽고 있습니다.

3.9.2 @Autowired 및 @Inject

아래 예를 이해할 수 없습니다. XML에서 작동하려면 무언가를해야합니까?

실시 예 1

public class SimpleMovieLister {

    private MovieFinder movieFinder;

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

    // ...
}

실시 예 2

public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

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

    // ...
}

두 클래스를 어떻게 자동으로 연결하여 동일한 인터페이스를 구현하고 동일한 클래스를 사용할 수 있습니까?

예:

class Red implements Color
class Blue implements Color

class myMainClass{
    @Autowired 
    private Color color;

    draw(){
        color.design(); 
    } 
}

어떤 설계 방법이 호출됩니까? Red 클래스의 디자인 메소드가 파란색이 아닌 호출되도록하려면 어떻게해야합니까?

답변:


542

TL; DR

@Autowired 어노테이션은 XML 파일 (또는 다른 방법)로 직접 배선을 수행 할 필요가 없으며 어디에서 삽입해야 하는지를 찾아서 수행합니다.

전체 설명

@Autowired주석은 다른 곳 주입 무엇의 구성을 생략 할 수 있으며 당신을 위해 그것을 않습니다. 패키지가 있다고 가정하면 com.mycompany.movies이 태그를 XML (응용 프로그램 컨텍스트 파일)에 넣어야합니다.

<context:component-scan base-package="com.mycompany.movies" />

이 태그는 자동 스캔을 수행합니다. Bean이되어야하는 각 클래스에 @Component(간단한 Bean의 경우) 또는 @Controller(서블릿 제어의 경우) 또는 @Repository( DAO클래스의 경우)와 같은 올바른 주석이 주석 처리되어 있고이 클래스가 패키지 아래 어딘가에 있다고 가정 com.mycompany.movies하면 Spring은 이들을 모두 찾아서 작성합니다. 각각의 콩. 이것은 두 개의 클래스 스캔에서 수행됩니다. 처음으로 Bean이되어야하는 클래스를 검색하고 수행해야하는 주입을 맵핑하고 두 번째 스캔에서 Bean을 주입합니다. 물론보다 전통적인 XML 파일이나 @Configuration 클래스 (또는이 세 가지의 조합)로 Bean을 정의 할 수 있습니다 .

@Autowired주입이 발생 할 필요가있는 주석이 봄을 알려줍니다. 메소드에 넣으면 Bean을 주입해야한다는 것을 setMovieFinder접두사 set+ @Autowired주석으로 이해 합니다. 두 번째 스캔에서 Spring은 유형의 Bean을 검색하고 MovieFinder이러한 Bean을 찾으면이 메소드에 삽입합니다. 그런 콩 두 개를 찾으면 Exception. 를 피하기 위해 주석을 Exception사용 @Qualifier하여 다음과 같은 방식으로 주입 할 두 개의 Bean 중 하나를 지시 할 수 있습니다 .

@Qualifier("redBean")
class Red implements Color {
   // Class code here
}

@Qualifier("blueBean")
class Blue implements Color {
   // Class code here
}

또는 XML로 Bean을 선언하려면 다음과 같이 보일 것입니다.

<bean id="redBean" class="com.mycompany.movies.Red"/>

<bean id="blueBean" class="com.mycompany.movies.Blue"/>

에서 @Autowired선언, 당신은 또한을 추가 할 필요가 @Qualifier주입하기 위해 두 가지 색상 콩의 어떤 말 :

@Autowired
@Qualifier("redBean")
public void setColor(Color color) {
  this.color = color;
}

두 개의 주석 ( @Autowired@Qualifier) 을 사용하지 않으려면 @Resource다음 두 가지를 결합 할 수 있습니다 .

@Resource(name="redBean")
public void setColor(Color color) {
  this.color = color;
}

@Resource(이 답변의 첫 번째 주석에 대한 몇 가지 여분의 데이터를 읽을 수 있습니다) 당신이 주석의 사용을 아끼지 대신 당신은 단지 하나를 사용하십시오.

코멘트를 두 개 더 추가하겠습니다.

  1. Spring 전용이 아니며 표준의 일부 이기 때문에 @Inject대신 사용하는 것이 좋습니다 .@AutowiredJSR-330
  2. 또 다른 좋은 방법은 메소드 대신 생성자에 @Inject/ 를 두는 @Autowired것입니다. 생성자에 배치하면 애플리케이션을 시작하려고 할 때 삽입 된 Bean이 널이 아니고 빠르게 실패하는지 검증하고 NullPointerException실제로 Bean을 사용해야 할 때를 피할 수 있습니다.

업데이트 : 그림을 완성하기 위해 수업 에 대한 새로운 질문을 만들었습니다 @Configuration.


6
'@Resource'는 JSR-250 표준의 일부이며 간단한 주입 이상으로 추가 의미가 있습니다 ( '@Autowired'는 Spring에서 왔으며 '@Inject'는 JSR-330) :)
Ignacio Rubio

경우 MovieFinder인터페이스이며, 우리의 콩이 MovieFinderImpl유형 또는 이름하여 주사한다 (콩 식의 MovieFinder), 봄 의지 자동차를?
Jaskey

@jaskey-사용 여부에 따라 다릅니다 @Qualifier. 당신이-이름으로하지 않으면-유형별로. 유형별은 MovieFinder컨텍스트에 하나의 유형의 Bean 만있는 경우에만 작동합니다 . 1 이상은 예외로 이어질 것입니다.
Avi

@Avi, 멋진 답변입니다. 그러나 예제 2@Autowiredprepare메소드에서 주석 이 어떻게 작동 하는지 이해하지 못합니다 . 그것은 초기화하는 것이지만 기술적으로 는 세터 가 아닙니다 . MovieRecommender
Karan Chadha

@KaranChadha- @Autowired생성자에도 적용됩니다. 필요한 종속성을 찾아 생성자에 삽입합니다.
Avi

21

이 예제에서 "같은 인터페이스를 구현하는 클래스"는 없습니다. MovieCatalog유형이며 CustomerPreferenceDao다른 유형입니다. 봄은 쉽게 구분할 수 있습니다.

Spring 2.x에서 Bean의 배선은 대부분 Bean ID 또는 이름을 통해 발생했습니다. 이것은 여전히 ​​Spring 3.x에서 지원되지만 종종 특정 유형의 Bean 인스턴스가 하나 있습니다. 대부분의 서비스는 싱글 톤입니다. 그것들의 이름을 만드는 것은 지루합니다. 그래서 스프링은 "자동 와이어 타입"을 지원하기 시작했습니다.

예제가 보여주는 것은 빈을 필드, 메소드 및 생성자에 주입하는 데 사용할 수있는 다양한 방법입니다.

XML에는 각 Bean에 완전한 클래스 이름을 지정해야하므로 Spring에 필요한 모든 정보가 이미 포함되어 있습니다. 그래도 인터페이스에 약간주의를 기울여야합니다.

이 자동 배선은 실패합니다 :

 @Autowired
 public void prepare( Interface1 bean1, Interface1 bean2 ) { ... }

Java는 바이트 코드에 매개 변수 이름을 유지하지 않기 때문에 Spring은 더 이상 두 Bean을 구별 할 수 없습니다. 해결 방법은 다음과 @Qualifier같습니다.

 @Autowired
 public void prepare( @Qualifier("bean1") Interface1 bean1,
     @Qualifier("bean2")  Interface1 bean2 ) { ... }

@AaronDigulla 그것은 좋았습니다. 그러나 함수를 어떻게 호출하는지 알고 싶습니다. prepare이 함수를 호출하는 데 어떤 매개 변수가 사용됩니까?
Nguyen Quang Anh

@NguyenQuangAnh 메소드를 호출하지 않고 Bean이 생성 될 때 Spring이 메소드를 호출합니다. 이것은 @Autowired필드가 주입 될 때 정확히 발생 합니다. 그런 다음 Spring은 매개 변수가 필요한지 확인하고 필드 주입에 사용 된 것과 동일한 규칙을 사용하여 매개 변수를 찾습니다.
Aaron Digulla

5

예, Bean (예 : 클래스)을 정의하도록 Spring 서블릿 컨텍스트 XML 파일을 구성하여 자동 삽입을 수행 할 수 있습니다. 그러나 Spring을 시작하고 실행하려면 다른 구성을 수행해야하며,이를 수행하는 가장 좋은 방법은 튜토리얼 기초를 따르는 것입니다.

당신이 당신의 봄은 아마 구성한 후에는 (작업 위의 예 1에 대한 봄 서블릿 컨텍스트 XML 파일에서 다음을 수행 할 수 있습니다하시기 바랍니다 교체 의 패키지 이름 com.movies을 이 제 3 자 경우 실제 패키지 이름이 무엇인지와 그런 다음 적절한 jar 파일이 클래스 경로에 있는지 확인하십시오) :

<beans:bean id="movieFinder" class="com.movies.MovieFinder" />

또는 MovieFinder 클래스에 기본 값을 가진 생성자가 있으면 다음과 같이 할 수 있습니다.

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg value="100" />
</beans:bean>

또는 MovieFinder 클래스에 다른 클래스를 기대하는 생성자가 있으면 다음과 같이 할 수 있습니다.

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg ref="otherBeanRef" />
</beans:bean>

... 여기서 ' otherBeanRef '는 예상되는 클래스에 대한 참조가있는 다른 Bean입니다.


4
XML에서 모든 배선을 정의하는 것은 단지 전체 아이디어를 놓치게됩니다@Autowired
Avi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.