私は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;
}
はこれを要約します。
セットアップでオートワイヤーを使用する方法はありますか?
これは確かに正しい方向への一歩です。残念ながら、私はリフレッシュループに陥っていました。最初のContextRefreshedEventは親コンテキストによってトリガされ、次のコンテキストは子コンテキストから来ていました。だから私は、createChildContext()は、イベントがルートコンテキストによって生成されたときにのみ呼び出されました。それはうまくいくように見えましたが、子コンテキストのTomcatは、SSLを使用してルートコンテキストのポートにバインドしようとします(親ではなく子に設定されています)。 –
更新:childContext.setParent(this.applicationContext);私は1つのContextRefreshedEventを取得し、elsethinfは動作します(親コンテクストからBeanにアクセスする以外には何もありません)。 –
サンプルプロジェクトをgithub:https://github.com/thomashoell/SpringBootChildContextにプッシュしました。興味深い部分は、ChildContextConfigクラスにあります。リフレッシュを呼び出す前に親コンテキスト**を設定すると、動作しません。私が気づいたことから、子コンテキストは親コンテキストの風袋を使用しているようです。 –