spring中父子容器的实现可以通过ConfigurableApplicationContext或ConfigurableBeanFactory来实现,这两个接口中分别有setParent及setParentBeanFactory方法,可以与当前的子容器进行父子容器关联,这个时候子容器就可以引用父容器中的bean,但是父容器是不能够引用子容器中的bean的,并且各个子容器中定义的bean是互不可见的,这样也可以避免因为不同的插件定义了相同的bean而带来的麻烦。应用场景包括插件或组件的接入,只需要对方提供JAR即可,由父容器进行引导,各个子容器再完成自己的应该完成的工作即可
package com.yaspeed.spring.parentChild;
public class Iphone7 {
private String name;
private int price;
public Iphone7(){
System.out.println("调用构造函数Iphone7()...");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Iphone7 [name=" + name + ", price=" + price + "]";
}
public void print(){
System.out.println("This is parent class.");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="iphone7" class="com.yaspeed.spring.parentChild.Iphone7" scope="singleton"
p:name="iphone7plus" p:price="7188">
</bean>
<bean id="pluginLoader" class="com.yaspeed.spring.parentChild.LoaderChild" init-method="load"></bean>
</beans>
package com.yaspeed.spring.parentChild;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class LoaderChild implements ApplicationContextAware{
ApplicationContext parentCtx;
ConfigurableApplicationContext childCtx;
public void load() {
childCtx = new ClassPathXmlApplicationContext("classpath*:/middleware_*.xml");
childCtx.setParent(parentCtx);
childCtx.refresh();
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.parentCtx = applicationContext;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="childCtx1" class="com.yaspeed.spring.parentChild.ChildCtx1"></bean>
<bean id="childCtx2" class="com.yaspeed.spring.parentChild.ChildCtx2"></bean>
</beans>
package com.yaspeed.spring.parentChild;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ChildCtx1 implements ApplicationContextAware {
ApplicationContext parentApplicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//父容器中没有建立父子容器关系之前,是获取不到parent的,只有父容器执行refresh方法后,第二次初使化子容器才会获取得到
//也就是第一次的初使化就不执行了,等父容器中建立好父子容器关系后再进行初使化,因为子容器需要引用父容器中的parentClass
if(applicationContext.getParent()==null){
return;
}
//Get parent application context
this.parentApplicationContext = applicationContext.getParent();
ConfigurableApplicationContext childCtx1 = new ClassPathXmlApplicationContext("classpath:/child1.xml");
childCtx1.setParent(this.parentApplicationContext);
childCtx1.refresh();
Iphone7 iphone7 = childCtx1.getBean(Iphone7.class);
System.out.println("childCtx1-->"+iphone7);
}
}
package com.yaspeed.spring.parentChild;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ChildCtx2 implements ApplicationContextAware {
ApplicationContext parentApplicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//父容器中没有建立父子容器关系之前,是获取不到parent的,只有父容器执行refresh方法后,第二次初使化子容器才会获取得到
//也就是第一次的初使化就不执行了,等父容器中建立好父子容器关系后再进行初使化,因为子容器需要引用父容器中的parentClass
if(applicationContext.getParent()==null){
return;
}
//Get parent application context
this.parentApplicationContext = applicationContext.getParent();
ConfigurableApplicationContext childCtx2 = new ClassPathXmlApplicationContext("classpath:/child2.xml");
childCtx2.setParent(this.parentApplicationContext);
childCtx2.refresh();
Iphone7 iphone7 = childCtx2.getBean(Iphone7.class);
System.out.println("childCtx2-->"+iphone7);
}
}
package com.yaspeed.spring.parentChild;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
public class Child1 implements InitializingBean {
//这里required加上false,是因为是没有建立父子容器关系之前,这个parentClass是注入不了了的
@Autowired(required = false)
Iphone7 parentClass;
//这里required加上false,是因为子容器之前是不能够相互引用的
@Autowired(required = false)
Child2 childClass2;
public void print() {
if (parentClass != null) {
parentClass.print();
}
System.out.println("This is child class 1");
if (childClass2 != null) {
System.out.println("childClass2 is not null!!");
childClass2.print();
}
}
public void afterPropertiesSet() throws Exception {
System.out.println("child1-->afterPropertiesSet...");
print();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"> </bean>
<bean id="child1" class="com.yaspeed.spring.parentChild.Child1"> </bean>
</beans>
package com.yaspeed.spring.parentChild;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
public class Child2 implements InitializingBean {
//这里required加上false,是因为是没有建立父子容器关系之前,这个parentClass是注入不了了的
@Autowired(required = false)
Iphone7 parentClass;
public void print() {
if (parentClass != null) {
parentClass.print();
}
System.out.println("This is child class 2");
}
public void afterPropertiesSet() throws Exception {
System.out.println("child2-->afterPropertiesSet...");
print();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"> </bean>
<bean id="child2" class="com.yaspeed.spring.parentChild.Child2"> </bean>
</beans>
package com.yaspeed.spring.parentChild;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
//启动父容器
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:/bean-parent.xml");
}
}
测试结果:
九月 19, 2016 3:39:51 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7106e68e: startup date [Mon Sep 19 15:39:51 CST 2016]; root of context hierarchy
九月 19, 2016 3:39:51 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from URL [file:/E:/workspace/drools/spring/bin/bean-parent.xml]
调用构造函数Iphone7()...
九月 19, 2016 3:39:52 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3f49dace: startup date [Mon Sep 19 15:39:52 CST 2016]; root of context hierarchy
九月 19, 2016 3:39:52 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from file [E:\workspace\drools\spring\bin\middleware_1.xml]
九月 19, 2016 3:39:52 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3f49dace: startup date [Mon Sep 19 15:39:52 CST 2016]; parent: org.springframework.context.support.ClassPathXmlApplicationContext@7106e68e
九月 19, 2016 3:39:52 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from file [E:\workspace\drools\spring\bin\middleware_1.xml]
九月 19, 2016 3:39:52 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@66480dd7: startup date [Mon Sep 19 15:39:52 CST 2016]; root of context hierarchy
九月 19, 2016 3:39:52 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [child1.xml]
child1-->afterPropertiesSet...
This is child class 1
九月 19, 2016 3:39:52 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@66480dd7: startup date [Mon Sep 19 15:39:52 CST 2016]; parent: org.springframework.context.support.ClassPathXmlApplicationContext@7106e68e
九月 19, 2016 3:39:52 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [child1.xml]
child1-->afterPropertiesSet...
This is parent class.
This is child class 1
childCtx1-->Iphone7 [name=iphone7plus, price=7188]
九月 19, 2016 3:39:52 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@22a67b4: startup date [Mon Sep 19 15:39:52 CST 2016]; root of context hierarchy
九月 19, 2016 3:39:52 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [child2.xml]
child2-->afterPropertiesSet...
This is child class 2
九月 19, 2016 3:39:52 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@22a67b4: startup date [Mon Sep 19 15:39:52 CST 2016]; parent: org.springframework.context.support.ClassPathXmlApplicationContext@7106e68e
九月 19, 2016 3:39:52 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [child2.xml]
child2-->afterPropertiesSet...
This is parent class.
This is child class 2
childCtx2-->Iphone7 [name=iphone7plus, price=7188]