2017-01-17 4 views
1

私は怒鳴るように依存するJARから1つの自動configuratonクラス内のBeanの作成すでに、ブートアプリケーションが春:Springブートアプリケーションで既存の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を交換したいが、私はまだ、この不要な豆を持って、このjarファイルを必要とします創造。そこで、私はメインの自動構成クラスに次のような別の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); 
    } 

しかし、これはターゲットBeanの置換に失敗しました。エラーメッセージは明確で分かりやすいです:

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] 

私の質問春のブートでこのような既存のbeanを置き換える正しい方法は何ですか?前もって感謝します。

答えて

2

この場合の問題は、このBeanをstaticRouteLocatorという名前に置き換えないことです。 patchedStaticRouteLocatorという名前の別のBeanを作成しています。これは一般的には問題ではありませんが、あなたが望むものではないようです。

@Primaryアノテーションも追加されており、少なくとも1つの主要な配線候補としてマークされたビーンが存在するため、NoUniqueBeanDefinitionExceptionが発生しました。春は今何をすべきか分からない。

最初のBeanを実際にオーバーライドする場合は、同じ名前を付けます。デフォルト名(他の名前が明示的に指定されていない場合)は、@Configurationクラスで定義するメソッドの名前になります。あなたの場合、これはpatchedStaticRouteLocatorになります。 (@Beanというアノテーションのあるプロパティで再度同じ名前を定義すると、それは冗長であり、必要ではない)

名前/エイリアスstaticRouteLocatorで置き換える場合は、新しいビーンに同じ名前、それが好きな定義:

@Bean(name="staticRouteLocator")

最初のBeanをオーバーライドする必要があること。

あなたは、このようなチェックであなたの豆を数えることができます。

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; 
    } 
} 
関連する問題