2016-09-29 6 views
3

Spring 프레임 워크의 문서를 읽을 때, 나는 공장에서 Bean 의존성을 전달하는 두 가지 스타일을 발견했습니다.Spring에서 Bean 의존성을 전달하기위한 바람직한 방법은 무엇입니까?

@Configuration 
public class MessagingConfiguration { 

    @Bean 
    public ConnectionFactory connectionFactory() { 
     CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost"); 
     connectionFactory.setUsername("guest"); 
     connectionFactory.setPassword("guest"); 
     return connectionFactory; 
    } 

    @Bean 
    public RabbitTemplate rabbitTemplate() { 
     return new RabbitTemplate(connectionFactory()); 
    } 

} 

두번째는 다음과 같다 (공장 메소드의 파라미터로서 의존성 주입) :

@Configuration 
public class MessagingConfiguration { 

    @Bean 
    public ConnectionFactory connectionFactory() { 
     CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost"); 
     connectionFactory.setUsername("guest"); 
     connectionFactory.setPassword("guest"); 
     return connectionFactory; 
    } 

    @Bean 
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { 
     return new RabbitTemplate(connectionFactory); 
    } 

} 

첫번째는 (직접 의존성 공장 메소드를 사용하여)이 같다 두 솔루션의 PRO 및 CON이 무엇이고 어느 것이 바람직한 지 알고 싶습니다.

답변

1

정상적인 사용 사례에서는 두 가지 접근 방식간에 큰 차이가 없어야합니다. 그러나 구성을 여러 클래스로 분할하려는 경우 첫 번째 솔루션을 단순히 사용할 수 없습니다. 두 개의 @Bean 메소드를 별도의 클래스에 넣고 @Import를 통해 두 번째 @Bean 메소드를 두 번째 클래스로 가져 오려고한다고 가정하면 컴파일러는 RabbitTemplate의 첫 번째 클래스 인 connectionFactory() 메소드를 알 수 없습니다 (connectionFactory)) 생성자입니다. 따라서 컴파일러 오류가 발생합니다. 수입 @Bean 정의

작품 위의 예에 Injecting dependencies on imported @Bean definitions

주입 종속성을하지만, 단순한입니다 :이 문제를 해결하려면 스프링 문서에서 권장하는 두 번째 방법을 사용할 수 있습니다. 실용적인 시나리오에서는 빈이 구성 클래스에 걸쳐 서로에 대한 종속성을 갖습니다. XML을 사용할 때 이것은 컴파일러가 관련되어 있지 않기 때문에 이 아니기 때문에 ref = "someBean"을 선언하고 컨테이너가 초기화하는 동안 스프링이이를 처리 할 것이라고 신뢰할 수 있습니다. 물론 @Configuration 클래스를 사용할 때 Java 컴파일러는 다른 bean에 대한 참조가 유효한 Java 구문이어야한다는 점에서 구성 모델에 제약 조건을 배치합니다.

다행히도이 문제를 해결하는 것은 간단합니다. 이미 논의한 것처럼 @Bean 메소드는 bean 의존성을 설명하는 임의의 수의 매개 변수를 가질 수 있습니다. 이제, 여러 @Configuration 클래스와 더 실제 시나리오를 생각해 보자 각 다른 사람에 선언 된 콩에 따라 :

@Configuration 
public class ServiceConfig { 

    @Bean 
    public TransferService transferService(AccountRepository accountRepository) { 
     return new TransferServiceImpl(accountRepository); 
    } 

} 

@Configuration 
public class RepositoryConfig { 

    @Bean 
    public AccountRepository accountRepository(DataSource dataSource) { 
     return new JdbcAccountRepository(dataSource); 
    } 

} 

@Configuration 
@Import({ServiceConfig.class, RepositoryConfig.class}) 
public class SystemTestConfig { 

    @Bean 
    public DataSource dataSource() { 
     // return new DataSource 
    } 

} 

public static void main(String[] args) { 
    ApplicationContext ctx = new  AnnotationConfigApplicationContext(SystemTestConfig.class); 
    // everything wires up across configuration classes... 
    TransferService transferService = ctx.getBean(TransferService.class); 
    transferService.transfer(100.00, "A123", "C456"); 
} 
0

두 번째 (코드 작성 시점에서 테스트를 고려한 경우). 코드를 테스트하거나 (예 : Mocking https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html) 구성하기가 훨씬 쉬워 지도록 종속 연결을 통해 하드 배선 및 인스턴스 생성을 항상 시도하십시오.

+0

당신이 하드 배선에 의해 무엇을 의미합니까? 두 조각은'RabbitTemplate'에 생성자 주입을 수행합니다. –

+0

첫번째 예제에서,'RabbitTemplate'은'connectionFactory()'메소드의 직접적인 결과를 사용합니다. – gtonic

+0

나는 OP가 아니야. 'connectionFactory'를 호출 한 결과가 캐시됩니다. 모든 호출은 동일한 값을 리턴합니다. –

1

"preferrable"에 대한 합의가 이루어지지 않는다고 생각합니다.

두 번째 스타일의 PRO는 종속 Bean이 정의 된 위치와 관계없이 그대로 작동한다는 것입니다. 문제의 두 콩은 두 개의 분리 된 @Configuration 클래스에 정의 된 경우

예를 들어, 스타일 일이 될 것입니다 :

@Configuration 
public class MessagingConfiguration1 { 

    @Bean 
    public ConnectionFactory connectionFactory() { 
     CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost"); 
     connectionFactory.setUsername("guest"); 
     connectionFactory.setPassword("guest"); 
     return connectionFactory; 
    } 

} 

@Configuration 
public class MessagingConfiguration2 { 

    @Autowired 
    ConnectionFactory connectionFactory;  

    @Bean 
    public RabbitTemplate rabbitTemplate() { 
     return new RabbitTemplate(this.connectionFactory); 
    } 

} 

을 두 번째 스타일은 그대로 유지 것이지만 :

@Configuration 
public class MessagingConfiguration1 { 

    @Bean 
    public ConnectionFactory connectionFactory() { 
     CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost"); 
     connectionFactory.setUsername("guest"); 
     connectionFactory.setPassword("guest"); 
     return connectionFactory; 
    } 

} 

@Configuration 
public class MessagingConfiguration1 { 

    @Bean 
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { 
     return new RabbitTemplate(connectionFactory); 
    } 

} 

두 번째 프로는 bean이 너무 많은 의존성을 가지고있는 것을 쉽게 볼 수있게 해준다. 이것은 너무 많은 일을 할 수도 있다는 것을 의미한다. 이것은 리팩터링을위한 시간이 될 수 있음을 의미한다.

몇 주 전까지 실제로 두 번째 스타일을 인식하지 못했지만 그 이후로 사용 해왔습니다.

행운을 빈다.

관련 문제