Spring:无法从父上下文 Autowiring bean

标签 spring spring-boot autowired applicationcontext

我有一个 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;
    }
}

到目前为止,这有效。但是当我尝试从父上下文 Autowiring bean 时,我收到一条错误,指出没有候选者。

另一件有趣的事情是,当我使用 ApplicationContextAware 接口(interface)将(子)上下文注入(inject)到我的子上下文的 bean 中时,该上下文的 getParent() 属性当时为 null。

我现在所做的是实现如下的 getter 函数:

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

总结一下:在构建子上下文的 bean 期间,未设置父上下文,因此我无法使用 Autowiring 。

有什么方法可以让 Autowiring 与我的设置配合使用吗?

最佳答案

构造函数使用类来注册在内部刷新上下文 - 尝试在设置父上下文后手动设置类和刷新。

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

关于Spring:无法从父上下文 Autowiring bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39121767/

相关文章:

java - Spring集成出站网关想要使用动态URL

javascript - 如何将输入标签更改为文本区域标签

java - 使用 gradle bootJar 而不是 jar 任务并且在 Jenkins 中构建失败

java - 为什么我的 Spring @Autowired 字段为空?

spring-boot - 如何在 Spring Boot 手动新建实例中使用@Autowired

java - Spring LDAP 3.1 自定义用户映射器

java - 如何将 web 服务的 xml 响应转换为所需的 xml 格式?

java - 如何在请求体中仅发送 id 而不是对象?

java - 如何将 spring.cloud.stream.kafka.bindings 配置属性应用于所有消费者

spring - Spring 请求和 session 范围有什么区别?