2017-01-17 2 views
1

나는 부팅 응용 프로그램을 봄이 이미 같은 우는 소리 종속 항아리에서 하나 개의 자동차 configuraton 클래스의 빈 생성 :봄 부팅 응용 프로그램에서 기존 bean을 바꾸는 방법은 무엇입니까?

@Bean 
@Order(100) 
public StaticRouteLocator staticRouteLocator(AdminServerProperties admin) { 
    Collection<ZuulRoute> routes = Collections 
      .singleton(new ZuulRoute(admin.getContextPath() + "/api/turbine/stream/**", 
        properties.getUrl().toString())); 
    return new StaticRouteLocator(routes, server.getServletPrefix(), zuulProperties); 
} 

지금 나는이 콩을 대체 할,하지만 난 여전히 원하지 않는 콩을 가지고이 항아리가 필요합니다 창조. 그래서 다음과 같이 메인 자동 설정 클래스에 또 다른 bean 생성 메소드를 추가했습니다 :

@Bean(name="patchedStaticRouteLocator") 
    @Order(10) 
    @Primary 
    @ConditionalOnMissingBean 
    public StaticRouteLocator patchedStaticRouteLocator(AdminServerProperties admin) { 
    Collection<ZuulProperties.ZuulRoute> routes = Collections 
     .singleton(new ZuulProperties.ZuulRoute(admin.getContextPath(), 
      properties.getUrl().toString())); 
    return new StaticRouteLocator(routes, server.getServletPrefix(), zuulProperties); 
    } 

그러나 이것은 대상 빈을 대체하지 못했습니다. 오류 메시지는 명확하고 이해하기 쉽습니다.

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.cloud.netflix.zuul.filters.RouteLocator] is defined: more than one 'primary' bean found among candidates: [routeLocator, patchedStaticRouteLocator, staticRouteLocator, compositeRouteLocator, applicationRouteLocator] 

제 질문은 스프링 부트에서 기존 빈을 바꿀 올바른 방법은 무엇입니까? 미리 감사드립니다.

답변

2

이 경우의 문제점은이 bean을 staticRouteLocator라는 이름으로 Y 꾸지 않는다는 것입니다. 다른 bean을 patchedStaticRouteLocator라는 이름으로 작성 중입니다. 이것은 일반적으로 문제가되지 않지만, 그것은 당신이 원하는 것이 아닌 것처럼 보입니다.

@Primary 주석을 추가 했으므로 NoUniqueBeanDefinitionException이 발생했으며 이제 기본 배선 후보로 표시된 빈이 두 개 이상 있습니다. 봄은 지금해야 할 일을 모른다.

첫 번째 빈을 실제로 덮어 쓰려면 동일한 이름을 지정하십시오. 기본 이름 (명시 적으로 다른 이름이 지정되지 않은 경우)은 @Configuration 클래스에 정의한 메소드의 이름입니다. 귀하의 경우이 patchedStaticRouteLocator 것입니다. (annotations name 속성을 사용하여 동일한 이름을 다시 정의하면 중복되거나 필요하지 않습니다.)

bean을 name/alias staticRouteLocator로 바꾸려면 새 bean을 동일하게 지정하십시오 이름, 그래서 좋아 정의 : 첫 번째 빈을 오버라이드 (override) 할 필요가

@Bean(name="staticRouteLocator")

합니다.

이 같은 검사와 콩을 셀 수 :

import static org.hamcrest.CoreMatchers.is; 
import static org.junit.Assert.assertThat; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.context.SpringBootTest; 
import org.springframework.context.ApplicationContext; 
import org.springframework.test.context.junit4.SpringRunner; 

@RunWith(SpringRunner.class) 
@SpringBootTest 
public class BeanConfigTest { 

    @Autowired 
    private ApplicationContext applicationContext; 

    @Test 
    public void countBeanNames() { 
     final String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); 
     assertThat(beanDefinitionNames.length, is(1)); 
    } 

} 

그냥 당신이 (전후) 기대 카운트 1을 교체합니다. BeanPostProcessor을 구현함으로써 달성

+0

감사합니다. 그러나 나는 그것을 'BeanPostProcessor' 컴포넌트를 구현함으로써 완성시켰다. – leo

+0

당신은 환영합니다. 그럼에도 불구하고 좋은 해결책을 찾았습니다. –

1

대상 : 예상대로이 솔루션이 작동하지 않았지만 내 혼란의 일부를 정리 위의 지침에 대한

@Component 
@Slf4j 
public class StaticRouteLocatorPostBeanProcessor implements BeanPostProcessor { 

    @Autowired 
    private TurbineProperties properties; 

    @Autowired 
    private ServerProperties server; 

    @Autowired 
    private ZuulProperties zuulProperties; 

    @Autowired 
    private AdminServerProperties adminServerProperties; 

    @Override 
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 
    return bean; 
    } 

    @Override 
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 
    if (StaticRouteLocator.class.isAssignableFrom(bean.getClass())) { 
     Collection<ZuulProperties.ZuulRoute> routes = Collections 
      .singleton(new ZuulProperties.ZuulRoute(adminServerProperties.getContextPath(), 
       properties.getUrl().toString())); 
     log.info("Began to replace the StaticRouteLocator bean."); 
     return new StaticRouteLocator(routes, server.getServletPrefix(), zuulProperties); 
    } 
    return bean; 
    } 
} 
관련 문제