Spring @Configuration 클래스 이해


108

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대신 어떻게 사용할 수 있습니까? 코드 자체에 영향을 미칩니 까?

답변:


151

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은 빈이 선언 된 메소드에 대해 신경 쓰지 않습니다.


2
한 가지 가능한 단점은 구성 손실입니다. 개발중인 일부 기능을 조롱하는 클래스가 있고 UAT 환경에서 다른 클래스로 교체하고 싶다고 가정 해 보겠습니다. XML을 사용하면 구성을 변경하고 응용 프로그램을 실행 / 재시작 할 수 있습니다. 이러한 새로운 클래스 구성을 사용하면 클래스를 다시 컴파일해야합니다.
Jose

5
@JoseChavez-그것은 내가 이미 몇 번 들었던 훌륭한 논쟁입니다. 그리고 병 / 전쟁 외부에서 XML을 사용하는 앱이나 시스템을 찾을 수없는 통계 조사를 시도했습니다. 실용적인 의미는 항아리의 압축을 풀고 XML을 변경하거나 (내가 그렇게하는 사람을 찾을 수 없었 음) 항아리를 다시 빌드해야한다는 것입니다 (지금까지 내가 말한 모든 사람이 말한 것입니다). . 따라서 결론-상당한 논쟁이 될 수 있으므로 일반적으로 실제 생활에서는 중요하지 않습니다.
아비

6
이것이 @Profile 주석 및 "$ {env.value}"구문의 용도입니다. @Profile ( "someName")을 사용하면 프로필이 활성화 된 경우에만 사용하도록 전체 구성에 태그를 지정할 수 있습니다. application.properties (또는 .yml) 파일에서 spring.profiles.active = someName, default ...를 설정할 수 있습니다. 환경 변수에 따라 동적으로 설정하려면 $ {SOME_ENV_VAR} 구문을 spring 값으로 사용하십시오. active.profiles 및 환경 변수를 설정하십시오. 봄은 이제 자바 설정을 사용하는 것이 좋습니다 - docs.spring.io/spring-boot/docs/current/reference/htmlsingle/...을
잭 Viers에게

구성 파일에서 각 Bean을 메소드로 정의하는 것보다 대안은 무엇입니까?
Asif Mushtaq

@AsifMushtaq-자동 스캔 기능을 사용할 수 있으며 @Component @Service이러한 주석 이 있거나 다른 주석이있는 각 클래스는 자동으로 빈으로 만들어집니다 (그러나이 질문의 초점은 아님)
Avi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.