2016-08-24 7 views
1

私はSpringブート(1.4.0)アプリケーションを持っています。これは初期化中に2番目のコンテキストを開始します(特定の種類の許可を使用してWebサービスを公開する必要があるため、親コンテキストは別のサービスを公開します)。Spring:親コンテキストからBeanをautowireできません

私はそうのような子コンテキスト作成:

@Configuration 
@ConditionalOnClass({Servlet.class, DispatcherServlet.class}) 
@ConditionalOnWebApplication 
public class ChildContextConfiguration implements ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> { 

    private final Logger logger = LoggerFactory.getLogger(ChildContextConfiguration.class); 
    private ApplicationContext applicationContext; 

    @Override 
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
     this.applicationContext = applicationContext; 
    } 

    private void createChildContext() { 
     final AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext(ChildConfiguration.class); 
     childContext.setParent(this.applicationContext); 
     childContext.setId(this.applicationContext.getId() + ":child"); 
    } 

    @Override 
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { 
     logger.info("creating child context"); 
     createChildContext(); 
    } 
} 

子コンテキストのコンフィギュレーション・クラスは次のようになります。これまでのところ

@Configuration 
@ComponentScan(basePackages = {"com.example.child"}) 
@PropertySource("file:some-config.properties") 
@ConfigurationProperties(prefix = "child") 
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) 
public class ChildConfiguration { 

    private Integer port; 
    private String keyStore; 
    private String keyStorePass; 
    private String keyPass; 
    private String trustStore; 
    private String trustStorePass; 
    private String packageBase; 

    public void setPort(Integer port) { 
     this.port = port; 
    } 

    public void setKeyStore(String keyStore) { 
     this.keyStore = keyStore; 
    } 

    public void setKeyStorePass(String keyStorePass) { 
     this.keyStorePass = keyStorePass; 
    } 

    public void setKeyPass(String keyPass) { 
     this.keyPass = keyPass; 
    } 

    public void setTrustStore(String trustStore) { 
     this.trustStore = trustStore; 
    } 

    public void setTrustStorePass(String trustStorePass) { 
     this.trustStorePass = trustStorePass; 
    } 

    public void setPackageBase(String packageBase) { 
     this.packageBase = packageBase; 
    } 

    @Bean 
    public Jaxb2Marshaller swpMarshaller() { 
     Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); 
     marshaller.setPackagesToScan(packageBase); 
     return marshaller; 
    } 

    @Bean 
    public Unmarshaller swpUnmarshaller() throws JAXBException { 
     JAXBContext jaxbContext = JAXBContext.newInstance(packageBase); 
     return jaxbContext.createUnmarshaller(); 
    } 

    @Bean 
    public Filter encodingFilter() { 
     CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter(); 
     encodingFilter.setEncoding("UTF-8"); 
     return encodingFilter; 
    } 

    @Bean 
    public ServerProperties serverProperties() { 
     ServerProperties props = new ServerProperties(); 
     props.setPort(port); 
     props.setSsl(ssl()); 

     return props; 
    } 

    private Ssl ssl() { 
     Ssl ssl = new Ssl(); 
     ssl.setEnabled(true); 
     ssl.setKeyStore(keyStore); 
     ssl.setKeyStorePassword(keyStorePass); 
     ssl.setKeyStoreType("JKS"); 
     ssl.setKeyPassword(keyPass); 
     ssl.setTrustStore(trustStore); 
     ssl.setTrustStorePassword(trustStorePass); 
     ssl.setClientAuth(Ssl.ClientAuth.NEED); 


     return ssl; 
    } 
} 

、これは動作します。しかし、親コンテキストからBeanをオートワイヤーしようとすると、候補がないというエラーが表示されます。

もう1つ興味深いのは、ApplicationContextAwareインターフェイスを使用して子コンテキストのBeanの1つに(子)コンテキストを注入すると、そのコンテキストのgetParent()プロパティがnullであることです。

私はこれらのようなゲッター機能を実装している今やっていること:子コンテキストの豆の建設時には、親コンテキストが設定されていないので、私はautowireを使用することはできません。

private SomeBean getSomeBean() { 
    if (this.someBean == null) { 
     this.someBean = applicationContext.getParent().getBean(SomeBean.class); 
    } 
    return this.someBean; 
} 

はこれを要約します。

セットアップでオートワイヤーを使用する方法はありますか?

答えて

1

登録するクラスを作成するコンストラクタは、コンテキストを内部的にリフレッシュします。親コンテキストを設定した後、クラスを設定して手動でリフレッシュしてみます。

private void createChildContext() { 
    final AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext(); 
    childContext.setParent(this.applicationContext); 
    childContext.setId(this.applicationContext.getId() + ":child"); 
    childContext.register(ChildConfiguration.class); 
    childContext.refresh(); 
} 
+0

これは確かに正しい方向への一歩です。残念ながら、私はリフレッシュループに陥っていました。最初のContextRefreshedEventは親コンテキストによってトリガされ、次のコンテキストは子コンテキストから来ていました。だから私は、createChildContext()は、イベントがルートコンテキストによって生成されたときにのみ呼び出されました。それはうまくいくように見えましたが、子コンテキストのTomcatは、SSLを使用してルートコンテキストのポートにバインドしようとします(親ではなく子に設定されています)。 –

+0

更新:childContext.setParent(this.applicationContext);私は1つのContextRefreshedEventを取得し、elsethinfは動作します(親コンテクストからBeanにアクセスする以外には何もありません)。 –

+0

サンプルプロジェクトをgithub:https://github.com/thomashoell/SpringBootChildContextにプッシュしました。興味深い部分は、ChildContextConfigクラスにあります。リフレッシュを呼び出す前に親コンテキスト**を設定すると、動作しません。私が気づいたことから、子コンテキストは親コンテキストの風袋を使用しているようです。 –

関連する問題