struts2与struts2-spring-plugin的整合

原文名称:使用 struts2 builder alias 机制加载objectFactory

以下代码基于 struts2 版本2.1.8.1 版本分析。

在使用 Struts2的过程中,我们都喜欢使用 struts2 的spring 插件来让 spring 作为struts2 的默认对象容器,原理就在于在加载 struts2 之前先加载 spring容器,然后将 spring 容器加载至 applicationContext中,在 struts2 的objectFactory (称之为对象容器)实现中,找到 spring 容器并进行各项对象创建工作。


 spring插件中,使用了 StrutsSpringObjectFactory 类来作为struts2 的对象容器,实现过程即除重写 objectFactory 的各项buildBean 方法以符合 spring 规范之外,其它则就是根据 struts2 的各项参数设置 spring参数(如 autoType 等)。之所以使用此类作为 struts2 的对象容器,原因就在于在 struts2-spring.jar 中的struts-plugin.xml 中定义了如下的声明:

<bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />

<constant name="struts.objectFactory" value="spring" />

第一句是声明了一个实现类 objectFactory 的对象,这就是 spring插件所提供的对象容器,而第二句则声明属性 struts.objectFactory 的值为spring ,即 key spring 的对象将成为 struts2的对象容器。


为什么这样说,我们可以看一下 struts2 对struts.objectFactory 的解释,以下解释摘自 struts2 中的default.properties:


### if specified, the default object factory can be overridden here

### Note: short-hand notation is supported in some cases, such as "spring"

###       Alternatively, you can provide a com.opensymphony.xwork2.ObjectFactory subclass name here


即只要设置了此值,则默认的对象容器,将被改写,那么 spring 插件所提供的功能就是定义了一个 spring 实现的对象容器,并且重写了 struts2 定义,将spring 容器再成为 struts2 的对象容器。

再反过来,我们可以看到 struts-default.xml 中也定义了如下的容器声明:


<bean class="com.opensymphony.xwork2.ObjectFactory" name="xwork" />

<bean type="com.opensymphony.xwork2.ObjectFactory" name="struts" class="org.apache.struts2.impl.StrutsObjectFactory" />


这里定义了两个 objectFactory 实现,一个为原生 xwork中的 objectFactory ,另一个则为 struts所提供的 strutsObjectFactory 。其中xwork  key xwork ,而struts  key struts 。


我们知道,在 struts2( 实际上就是 xwork),所确定最终的 objectFactory 的实现体是需要找一个类型为 ObjectFactory ,key 值为 default的实现类,而这 2 个xml 定义中都没有提到 default 这个key 值,那么就是在程序内部所实现了的。


首先看, struts2 是如何寻找 objectFactory实现的,类 DefaultConfiguration 中第181 行至 186行,如何上就是如何创建整个 struts2 容器,并确定对象容器的过程。如下代码所示:


// Set the bootstrap container for the purposes of factory creation

Container bootstrap = createBootstrapContainer();

setContext(bootstrap);

container = builder.create(false);

setContext(container);

objectFactory = container.getInstance(ObjectFactory.class);


上文中的 builder.create(false) 即是创建容器的过程,而 container.getInstance(ObjectFactory.class) 则是取得(创建)对象容器的过程。那么实际上,在 builder.create(false) 过程中,实际的对象容器已经确定了,即 key 为default, 类型为 ObjectFactory的类已经注入到容器中了。那么这个信息是如何注入的呢,这就归结于 builder (即ContainerBuilder )所提供的 alias 机制了。


什么叫 alias?熟悉 spring 的就知道,其实就是一个别名嘛,我们可以将一个 id 的aaBean 的对象定义一个别名叫 bbBean ,那么在struts2 中,我们也可以将 key 为spring 的对象,定义一个别名叫 default !


这就是程序内部实现的原理了,就是找到属性名为 struts.objectFactory 的属性值,然后将此属性值定义一个别名为 default ,此后就将此对象作为 Struts2容器最终找到的对象了。


那么终需要一个对象来调用 builder 的alias 方法吧,此类就是 BeanSelectionProvider ,在初始化 struts2容器时,此类被作为 containerProvider 提供给containerBuilder ,那么在后面肯定会用到此类了。其实就是在初始化之前提供各项信息给 builder ,那么它提供的信息是哪些呢,在方法 public void register(ContainerBuilder builder, LocatableProperties props) 中实现 如下:

alias(ObjectFactory.class, StrutsConstants.STRUTS_OBJECTFACTORY, builder, props);

alias(XWorkConverter.class, StrutsConstants.STRUTS_XWORKCONVERTER, builder, props);

alias(TextProvider.class, StrutsConstants.STRUTS_XWORKTEXTPROVIDER, builder, props, Scope.DEFAULT);


我们关注的就是第一行,即这里一个,其代码为 :

alias(ObjectFactory.class, “struts.objectFactory”, builder, props);


需要注意的是,这里的 alias 和containerProvider 所提供的 alias 还不一样。 containerProvider alias 是直接将给定的 name定义为别名,而此处的 alias 是指将给定的 name所对应的值定义为别名,相当于中间处了一次处理。为什么处理成这样,其实就是一个扩展的过程。那么我们来看一下相应的实现:


if (!builder.contains(type)) {// 相当于builder.contains(type,”default”)

   String foundName = props.getProperty(key, DEFAULT_BEAN_NAME);// 这里的 DEFAULT_BEAN_NAME struts

if (builder.contains(type, foundName)) {

builder.alias(type, foundName, Container.DEFAULT_NAME);

   ……

首先寻找类型为 objectFactory, 且key  default的声明,如前所示,肯定找不到的啦。那么就在定义文件中寻找声明为 struts.objectFactory 的值,在这里我们找到了其值为 spring ,接下来就将 key spring 的定义加个别名为 default。在后面就找到了相应对象容器实现了。


需要注意的是, props.getProperty(key, DEFAULT_BEAN_NAME); 此句意为在没有找到值的情况下,就使用默认值,而默认值就是 struts ,意思是需要不存在 spring插件,则直接使用 key 为struts 所对象的对象,即 StrutsObjectFactory 来作为对象容器了。

<bean type="com.opensymphony.xwork2.FileManagerFactory" class="com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory" name="xwork" scope="singleton"/>

<bean type="com.opensymphony.xwork2.FileManagerFactory" class="com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory" name="struts" scope="singleton"/>


转载请标明出处:i flym
本文地址:http://www.iflym.com/index.php/code/201204050001.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值