2016-08-24 3 views
1

Ich habe eine Spring Boot (1.4.0) Anwendung, die während der Initialisierung einen zweiten Kontext startet (ich brauche das, weil ich einen Webdienst mit einer bestimmten Art von Autorisierung veröffentlichen muss) während der Elternkontext einen anderen Dienst veröffentlicht).Spring: Ich kann die Beans vom übergeordneten Kontext nicht autowire

Ich habe ein Kind Zusammenhang wie folgt:

@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(); 
    } 
} 

Die Konfigurationsklasse des Kindes Kontext wie folgt aussieht:

@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; 
    } 
} 

Bisher dies funktioniert. Aber wenn ich versuche, eine Bean aus dem übergeordneten Kontext zu starten, bekomme ich eine Fehlermeldung, dass es keinen Kandidaten gibt.

Eine weitere interessante Sache ist, wenn ich den (untergeordneten) Kontext in eine der Beans meines Kindkontexts über die ApplicationContextAware-Schnittstelle injiziere, ist die getParent() -Eigenschaft dieses Kontexts zu diesem Zeitpunkt null.

Was ich jetzt getan haben, ist Getter Funktionen wie diese Umsetzung:

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

das Fassen wir zusammen: Beim Bau der Bohnen des Kindes Kontext, der Elternkontext nicht gesetzt ist, so kann ich nicht autowire verwenden.

Gibt es eine Möglichkeit, Autowire mit meinem Setup arbeiten zu lassen?

Antwort

1

Konstruktor, der Klassen zur internen Aktualisierung des Refresh-Kontexts verwendet - versuchen Sie, die Klasse und die Aktualisierung manuell festzulegen, nachdem der übergeordnete Kontext festgelegt wurde.

+0

Dies ist sicherlich ein Schritt in die richtige Richtung. Leider steckte ich in einer Refresh-Schleife fest. Das erste ContextRefreshedEvent wurde vom übergeordneten Kontext ausgelöst, die folgenden stammen vom untergeordneten Kontext. Also habe ich createChildContext() nur aufgerufen, wenn das Ereignis vom Root-Kontext ausgegeben wird. Das schien zu funktionieren, aber dann versucht der tomcat des Kindkontextes, an den Port des root-Kontexts zu binden, ABER unter Verwendung von SSL (das für das untergeordnete Element und nicht für das übergeordnete Element konfiguriert ist) –

+0

Update: Wenn ich auskommentiere childContext.setParent (this.applicationContext); Ich bekomme nur ein ContextRefreshedEvent und alles funktioniert (neben dem Zugriff auf Beans aus dem übergeordneten Kontext, da keiner vorhanden ist). –

+0

Ich schob ein Beispielprojekt nach github: https://github.com/thomashoell/SpringBootChildContext. Der interessante Teil befindet sich in der Klasse ChildContextConfig. Wenn ich den Elternkontext ** BEFORE ** aufrufen, refresh, funktioniert es nicht. Nach dem, was ich bemerkt habe, scheint der Kindkontext den Kater des Elternkontextes zu verwenden. –

Verwandte Themen