[java] Spring @Configuration 클래스 이해

Spring @Autowired 사용법 이해 라는 질문에 따라 Spring Wireing 의 다른 옵션 인 @Configuration클래스에 대한 완전한 지식 기반을 만들고 싶었습니다 .

다음과 같은 스프링 XML 파일이 있다고 가정 해 보겠습니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <import resource="another-application-context.xml"/>

  <bean id="someBean" class="stack.overflow.spring.configuration.SomeClassImpl">
    <constructor-arg value="${some.interesting.property}" />
  </bean>

  <bean id="anotherBean" class="stack.overflow.spring.configuration.AnotherClassImpl">
    <constructor-arg ref="someBean"/>
    <constructor-arg ref="beanFromSomewhereElse"/>
  </bean>
</beans>

@Configuration대신 어떻게 사용할 수 있습니까? 코드 자체에 영향을 미칩니 까?



답변

XML 마이그레이션 @Configuration

@Configuration몇 단계 만 거치면 xml을로 마이그레이션 할 수 있습니다 .

  1. @Configuration주석이 달린 클래스를 만듭니다 .

    @Configuration
    public class MyApplicationContext {
    
    }
    
  2. <bean>태그에 대해 다음 과 @Bean같이 주석이 달린 메소드를 만듭니다 .

    @Configuration
    public class MyApplicationContext {
    
      @Bean(name = "someBean")
      public SomeClass getSomeClass() {
        return new SomeClassImpl(someInterestingProperty); // We still need to inject someInterestingProperty
      }
    
      @Bean(name = "anotherBean")
      public AnotherClass getAnotherClass() {
        return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse); // We still need to inject beanFromSomewhereElse
      }
    }
    
  3. 수입하기 위해 beanFromSomewhereElse우리는 정의를 가져와야합니다. XML로 정의 할 수 있으며 다음을 사용할 것입니다 @ImportResource.

    @ImportResource("another-application-context.xml")
    @Configuration
    public class MyApplicationContext {
      ...  
    }
    

    Bean이 다른 @Configuration클래스에 정의되어 있으면 @Import주석을 사용할 수 있습니다 .

    @Import(OtherConfiguration.class)
    @Configuration
    public class MyApplicationContext {
      ...
    }
    
  4. 다른 XML이나 @Configuration클래스를 가져온 후에는 @Configuration다음과 같이 클래스에 개인 멤버를 선언하여 컨텍스트에서 선언 한 Bean을 사용할 수 있습니다 .

    @Autowired
    @Qualifier(value = "beanFromSomewhereElse")
    private final StrangeBean beanFromSomewhereElse;
    

    또는 이에 의존하는 Bean을 정의하는 메소드에서 다음과 같이 매개 변수로 직접 beanFromSomewhereElse사용 @Qualifier합니다.

    @Bean(name = "anotherBean")
    public AnotherClass getAnotherClass(@Qualifier (value = "beanFromSomewhereElse") final StrangeBean beanFromSomewhereElse) {
      return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse);
    }
    
  5. 속성 가져 오기는 다른 xml 또는 @Configuration클래스 에서 bean을 가져 오는 것과 매우 유사합니다 . 사용하는 대신 다음과 같이 속성과 함께 @Qualifier사용 @Value합니다.

    @Autowired
    @Value("${some.interesting.property}")
    private final String someInterestingProperty;
    

    이것은 SpEL 표현식 에서도 사용할 수 있습니다 .

  6. Spring이 이러한 클래스를 Bean 컨테이너로 취급 할 수 있도록하려면이 태그를 컨텍스트에 넣어 메인 xml에 표시해야합니다.

    <context:annotation-config/>

    이제 @Configuration간단한 빈을 만드는 것과 똑같은 클래스를 가져올 수 있습니다 .

    <bean class="some.package.MyApplicationContext"/>

    스프링 XML을 모두 피하는 방법이 있지만이 답변의 범위에 포함되지 않습니다. 이 옵션 중 하나는 내 답변을 기반으로하는 내 블로그 게시물 에서 찾을 수 있습니다 .


이 방법 사용의 장단점

기본적으로 다음과 같은 몇 가지 장점으로 인해 XML을 사용하는 것보다 빈을 선언하는이 방법이 훨씬 더 편합니다.

  1. 오타@Configuration클래스가 컴파일되고 오타는 컴파일을 허용하지 않습니다.
  2. 빠른 실패 (컴파일 시간) -빈을 주입하는 것을 잊은 경우 XML과 같이 런타임이 아닌 컴파일 시간에 실패합니다.
  3. IDE에서 더 쉽게 탐색 -종속성 트리를 이해하기 위해 Bean 생성자 간.
  4. 구성 시작을 쉽게 디버그 가능

단점은 내가보기에 그리 많지 않지만 몇 가지 생각할 수 있습니다.

  1. 남용 -코드는 XML보다 남용하기 쉽습니다.
  2. XML을 사용하면 컴파일 타임에는 사용할 수 없지만 런타임에는 제공되는 클래스를 기반으로 종속성을 정의 할 수 있습니다. @Configuration클래스를 사용하면 컴파일 타임에 사용할 수있는 클래스가 있어야합니다. 일반적으로 문제가되지 않지만 문제가있을 수있는 경우가 있습니다.

결론 : 애플리케이션 컨텍스트에서 XML @Configuration주석 을 결합하는 것은 완벽합니다 . Spring은 빈이 선언 된 메소드에 대해 신경 쓰지 않습니다.


답변