本文讲述Seam组件的初始化和实例化过程。
[b][size=medium]初始化seam组件[/size][/b]
SeamListener.contextInitialized(...)
new Initialization(servletContext).create().init();
Initialization.create()
StandardDeploymentStrategy.scan();
通过UrlScanner 扫描包含 seam.properties, META-INF/seam.properties 或 META-INF/components.xml的文件夹和jar文件。
ComponentDeploymentHandler.handle(...)
针对每一个扫描到的ClassFile, 如满足以下两个条件,则标记为seam 组件:
1. 有@Name标注或有一个同名的.component.xml文件存在;
2. 无@Install标注或有@Install 标注且 value = false;
initComponentsFromXmlDocument("/WEB-INF/components.xml")
安装WEB-INF/components.xml中定义的组件;
initComponentsFromXmlDocuments();
安装所有META-INF/components.xml中定义的组件;
Initialization.init()
scanForComponents()
安装StandardDeploymentStrategy扫描到的seam组件;
addComponent( new ComponentDescriptor(Init.class), ...)
安装Init组件;
addSpecialComponents(init)
安装PojoCache组件;
installComponents(init)
安装依赖组件?
Initialization.addComponent(descriptor, context)
component = new Component(...);
context.set(componentName, component);
所有的Seam组件都安装到了ApplicationContext中了.下面我们来看如何获得组件。
[b][size=medium]Seam组件的实例化[/size][/b]
即然组件交由seam来管理,那么就不能使用new来实例化了,必须通过Component对象来完成。
Component.newInstance()
Component.instantiate()
根据组件的类型执行不同的实例化操作。
[b]Pojo组件的实例化[/b]
Component.instantiateJavaBean()
判断此组件是否允许被Interceptor,这由BypassInterceptors描述决定,
如允许被Interceptor,则创建Proxy对象并加入interceptor对象,
有关Interceptor的内容我们将在下一篇文章中详述。
[b]Entity组件的实例化[/b]
Component.instantiateEntityBean()
Object bean = getBeanClass().newInstance();
initialize(bean);
[b]Session组件的实例化[/b]
Component.instantiateSessionBean()
Object bean = Naming.getInitialContext().lookup(jndiName);
return wrap(bean, new ClientSideInterceptor(bean, this));
Session组件由JNDI进行管理,获得Session组件后,创建一个Proxy对象对它进行封装,
ClientSideInterceptor为客户端的拦截器。
[b][size=medium]Seam组件的调用[/size][/b]
通过Component类,可以非常容易的获得seam组件,查找的顺序如下:
1. Seam从给定的Scope Context中查找,如未指定Scope,则查找所有Context;
2. 如未找到组件,则查找是否有工厂方法;
3. 如未找到工厂方法,则使用newInstance方法实例化组件并存入相应Scope的Context中;
4. unwrap组件;
Component.getInstance(name)
// 查找所有Context
Object result = Contexts.lookupInStatefulContexts(name);
result = getInstance(name, create, result);
return result;
Component.getInstance(name, scope)
// 查找scope的Context
Object result = scope==STATELESS ? null : scope.getContext().get(name);
result = getInstance(name, create, result);
return result;
Component.getInstance(name, create, result)
[b][size=medium]初始化seam组件[/size][/b]
SeamListener.contextInitialized(...)
new Initialization(servletContext).create().init();
Initialization.create()
StandardDeploymentStrategy.scan();
通过UrlScanner 扫描包含 seam.properties, META-INF/seam.properties 或 META-INF/components.xml的文件夹和jar文件。
ComponentDeploymentHandler.handle(...)
针对每一个扫描到的ClassFile, 如满足以下两个条件,则标记为seam 组件:
1. 有@Name标注或有一个同名的.component.xml文件存在;
2. 无@Install标注或有@Install 标注且 value = false;
initComponentsFromXmlDocument("/WEB-INF/components.xml")
安装WEB-INF/components.xml中定义的组件;
initComponentsFromXmlDocuments();
安装所有META-INF/components.xml中定义的组件;
Initialization.init()
scanForComponents()
安装StandardDeploymentStrategy扫描到的seam组件;
addComponent( new ComponentDescriptor(Init.class), ...)
安装Init组件;
addSpecialComponents(init)
安装PojoCache组件;
installComponents(init)
安装依赖组件?
Initialization.addComponent(descriptor, context)
component = new Component(...);
context.set(componentName, component);
所有的Seam组件都安装到了ApplicationContext中了.下面我们来看如何获得组件。
[b][size=medium]Seam组件的实例化[/size][/b]
即然组件交由seam来管理,那么就不能使用new来实例化了,必须通过Component对象来完成。
Component.newInstance()
instance = instantiate();
if (getScope()!=STATELESS) {
//存入Context,
getScope().getContext().set(name, instance);
......
}
Component.instantiate()
switch(type) {
case JAVA_BEAN:
return instantiateJavaBean();
case ENTITY_BEAN:
return instantiateEntityBean();
case STATELESS_SESSION_BEAN:
case STATEFUL_SESSION_BEAN:
return instantiateSessionBean();
......
}
根据组件的类型执行不同的实例化操作。
[b]Pojo组件的实例化[/b]
Component.instantiateJavaBean()
Object bean = getBeanClass().newInstance();
if (!interceptionEnabled) {
initialize(bean);
callPostConstructMethod(bean);
}
else {
JavaBeanInterceptor interceptor = new JavaBeanInterceptor(bean, this);
bean = wrap(bean, interceptor); // 创建Proxy对象
interceptor.postConstruct(); // 由PostConstruct调用initialize(bean)
}
判断此组件是否允许被Interceptor,这由BypassInterceptors描述决定,
如允许被Interceptor,则创建Proxy对象并加入interceptor对象,
有关Interceptor的内容我们将在下一篇文章中详述。
[b]Entity组件的实例化[/b]
Component.instantiateEntityBean()
Object bean = getBeanClass().newInstance();
initialize(bean);
[b]Session组件的实例化[/b]
Component.instantiateSessionBean()
Object bean = Naming.getInitialContext().lookup(jndiName);
return wrap(bean, new ClientSideInterceptor(bean, this));
Session组件由JNDI进行管理,获得Session组件后,创建一个Proxy对象对它进行封装,
ClientSideInterceptor为客户端的拦截器。
[b][size=medium]Seam组件的调用[/size][/b]
通过Component类,可以非常容易的获得seam组件,查找的顺序如下:
1. Seam从给定的Scope Context中查找,如未指定Scope,则查找所有Context;
2. 如未找到组件,则查找是否有工厂方法;
3. 如未找到工厂方法,则使用newInstance方法实例化组件并存入相应Scope的Context中;
4. unwrap组件;
Component.getInstance(name)
// 查找所有Context
Object result = Contexts.lookupInStatefulContexts(name);
result = getInstance(name, create, result);
return result;
Component.getInstance(name, scope)
// 查找scope的Context
Object result = scope==STATELESS ? null : scope.getContext().get(name);
result = getInstance(name, create, result);
return result;
Component.getInstance(name, create, result)
if (result == null && create) {
// 通过工厂模式创建.
result = getInstanceFromFactory(name);
if (result == null) {
if (component== null) {
}
else if (component.getScope().isContextActive()) {
// 检查Context是否为激活状态
result = component.newInstance();
}
}
if (result != null) {
if (component != null) {
if (!component.isInstance(result)) {
// 检查result为有效的bean实例
if (component.hasUnwrapMethod())
return result;
}
result = component.unwrap(result);
}
}
return result;
}