2017-01-17 18 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

Проблема в этом случае заключается в том, что вы не заменяете этот компонент именем staticRouteLocator. Вы создаете еще один компонент с именем patchedStaticRouteLocator. Это вообще не проблема, но, похоже, это не то, что вы хотите.

Поднят номер NoUniqueBeanDefinitionException, так как вы также добавили аннотацию @Primary, и теперь есть как минимум две фасоли, отмеченные как первичный кандидат на проводку. Весна не знает, что она должна делать сейчас.

Если вы действительно хотите переопределить первый компонент, дайте ему то же имя. Имя по умолчанию (если не указано иное явно не указано) будет именем метода, который вы определяете в своем классе @Configuration. В вашем случае это будет patchedStaticRouteLocator. (На данный момент вы также определить то же имя снова с @Bean аннотациями name собственности, это своего рода излишними и не нужны.)

Если вы хотите, чтобы заменить компонент с именем/псевдонимом staticRouteLocator, дайте новый Бин же назовете, так определяют это нравится:

@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 с графом вы ожидаете (до и после).

+0

Спасибо за выше инструкции, которые излечение некоторые из моих неурядиц, хотя это решение не работало, как ожидалось. Однако я сделал это, выполнив компонент «BeanPostProcessor». – leo

+0

Добро пожаловать. Тем не менее приятно, что вы нашли рабочее решение. –

1

Цель достигается путем внедрения BeanPostProcessor:

@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; 
    } 
}