[java] Spring @Autowired 사용법 이해

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 클래스의 디자인 메소드가 파란색이 아닌 호출되도록하려면 어떻게해야합니까?



답변

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.


답변

이 예제에서 “같은 인터페이스를 구현하는 클래스”는 없습니다. 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 ) { ... }


답변

예, 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입니다.


답변