在大峡的文章在EasyJWeb使用spring容器中讲解了如何在easyjweb中集成使用spring,今天我们来了解一下EasyJWeb中集成集成子容器的原理。
要知道EasyJWeb集成spring的原理我们就需要先了解EasyJWeb容器的初始化过程及工作原理。EasyJWeb中提供了一个Container接口,所有容器实现这个接口。Container接口定义了bean操作的几个通用方法,代码如下:
public interface Container {
/**
* 根据名称从容器中返回一个Bean
*
* @param name
* 要查找的bean名称
* @return 若存在该名称的bean则返回该bean对象,若没有找到指定名称的bean,则返回null
*/
Object getBean(String name);
/**
* 从容器中查询一个类型为type的Bean
*
* @param type
* 要查找的Bean类型
* @return 若存在该类型的bean则返回第一个符合该类型的bean,若没有找到指定类型的bean,则返回null
*/
Object getBean(Class type);
/**
* 在容器中查找所有类型为type的Bean
*
* @param type
* 要查找的bean类型,可以是接口、抽象类或具体的类
* @return 若找到符合条件Bean,则返回一个List列表,否则返回null
*/
List getBeans(Class type);
/**
* 判断容器中是否包含指定名称的Bean
*
* @param name
* 需要查找的bean名称
* @return 若存在指定名称的bean则返回true,否则返回false
*/
boolean containsBean(String name);
/**
* 得到容器中所有Bean的名称
*
* @return 返回容器中存在的所有Bean的名称集合,包括匿名Bean
*/
Collection getBeansName();
}
EasyJWeb默认提供一个DefaultContainer实现Container接口。EasyJWeb的容器在DefaultContainer的refresh方法中初始化,但是这个方法不在Container接口中,不知道大峡当初这样设计是出于怎样的考虑。
为了能方便的集成其它容器,EasyJWeb提供了另外一个接口InnerContainer,这个接口继承自Container,并另外提供了三个方法:init()、setParent(Container container)、getParent()。如果你需要集成某个容器的话只需要写一个类实现该接口,然后稍作配置就可以了。现在我们看看EasyJWeb中的子容器是如何初始化的。
EasyJWeb容器的直接初始化操作是在DefaultContainer的create方法中,由于这个方法的代码很长,我只将初始化子容器的这部分代码贴出来:
if (bean != null && bean instanceof InnerContainer
&& !containers.containsKey(beanDefinition.getBeanName())) {
logger.info(I18n
.getLocaleMessage("core.container.loaded.a.container") + bean);
InnerContainer innerContainer = (InnerContainer) bean;
innerContainer.setParent(this);
innerContainer.init();
containers.put(beanDefinition.getBeanName(), innerContainer);
}
create方法用来创建EasyJWeb配置文件中配置的bean,它在创建玩bean之后会判断一下这个bean是不是一个InnerContainer,如果是就执行init方法初始化该子容器,并将初始化完毕的子容器放入containers(存放子容器的一个map)中。因此,要集成某个容器,只要写一个类实现InnerContainer接口,并在init方法中初始化你所使用的容器就可以了。从上面这段代码可以看出来,理论上EasyJWeb是可以同时使用多个子容器的,但是我没有对这个进行过测试,有兴趣的可以自己尝试一下。
那么EasyJWeb又是如何使用子容器的呢?很简单,我们看看DefaultContainer的getBean(String name)方法就知道了:
public Object getBean(String name) {
Object bean = super.getSingletionBean(name);
if (bean == null) {
BeanDefinition definition = (BeanDefinition) beanDefinitions
.get(name);
if (definition != null)
bean = create(definition);
else
for (Container innerContainer : containers.values()) {
bean = innerContainer.getBean(name);
if (bean != null)
break;
}
}
return bean;
}
代码也很简单,先从父类获取一个名为name的SingletionBean,如果没有,就从默认容器中找,如果还没有,就遍历子容器来找。
EasyJWeb提供了一个默认的集成spring的解决方案,就是com.easyjf.container.impl.SpringContainer.java这个类。spring的初始化工作就在这个类的init()方法中执行。代码很简单,就不做具体说明了。如果你觉得这个类写得不好,想自己写一个spring集成类也可以,实现InnerContainer接口,然后修改一下配置就好了。