我有一个Spring Boot(1.4.0)应用程序,它在初始化期间启动第二个上下文(我需要这个,因为我必须使用特定类型的授权发布Web服务,而父上下文发布不同的服务)。
我创建了一个像这样的子上下文:
@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时,我收到一条错误,指出没有候选者。
另一件有趣的事情是,当我使用ApplicationContextAware接口将(子)上下文注入我的子上下文的bean之一时,该上下文的getParent()属性在那时为空。
我现在所做的是实现这样的getter函数:
private SomeBean getSomeBean() {
if (this.someBean == null) {
this.someBean = applicationContext.getParent().getBean(SomeBean.class);
}
return this.someBean;
}
总结一下:在构造子上下文的bean期间,没有设置父上下文,所以我不能使用autowire。
有没有办法让autowire与我的设置一起工作?
答案 0 :(得分: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();
}