上篇博客介绍了Struts1.X与Spring集成的一种方案。Struts1.X与Spring集成——第一种方案
此篇博客还以上篇博客的登录例子为例,介绍Struts1.X与Spring集成的另一种方案。
1,第一种方案 原理
回忆第一种方案集成原理:在Action中取得BeanFactory,通过BeanFactory取得业务逻辑对象
此种方案的缺点:从严格意义的分层上来看,Action上看到了Spring的相关东西,依赖Spring
API去查找东西,发生了依赖查找,因为要查找依赖对象,所以要依赖Spring服务才能找到,因为在Spring提供的工厂里。应该是Action中看不到Spring相关东西,Action中看到的就是业务接口,这样的话层次更加分明。
2,第二种方案 原理
基于第一种方案的缺点,我们改成不在去查找业务对象,让IOC注入进来,只要提供setter方法,就能把对象主动传过来——依赖注入(局限性:在同一个JVM里可以,跨JVM不可以依赖注入)
如果想被Spring注入,Action需要被Spring管理,也就是说LoginAction的创建是从IOC容器中创建出来的,而不应该再是让Struts创建。如果还是Struts创建的话,UserManager是不可能注入进来的。只有从IOC容器中拿出来的东西,所有的依赖关系才被注入,所以Action必须被Spring管理,被Spring管理,就需要配置到Spring的配置文件中。
applicationContext-beans.xml:
applicationContext-action.xml:
只要通过BeanFactory getBean()把"LoginAction"拿到,同时userManager的依赖关系都会注入进去;
3,分析第二种方案提出的原由
第一种方案:
Web客户端发出请求,请求ActionServlet,Struts流程是在Struts里面要查看Struts-config.xml,把LoginAction拿出来new,如下:
Struts进行new,只会new LoginAction,其他的UserManager不会new,也不会注入。
所以此种流程是不行的,依赖对象不能注入。
但是,用Struts的话必须得请求Action,所以需要使用Spring,Spring实现了一个Action(Action代理类:ActionProxy)——不会改变原先Action的相关接口,只是代理,代理可以控制原目标,在调目标之前可以做些事情。所以Struts-config.xml文件中就不应该配置LoginAction.java这个类了,要配置Spring给提供的一个类,它提供的类起到了什么作用:web客户端发出请求,需要Struts把Spring提供的代理类new出,这个代理类中负责拿到BeanFactory,通过getBean(),把这次请求对应的Action拿出来(是从IOC容器中拿出LoginAction),那么它的依赖对象就都会被注入。如下图第二种方案:
第二种方案:
将第一种方案,Struts-config.xml中配置的LoginAction.Java类(如下图(1))改为配置org.springframework.web.struts.DelegatingActionProxy.class(2)
(1)
(2)
(3)
applicationContext-action.xml:配置LoginAction类,来管理LoginAction类
一个请求过来,Struts中new出代理类DelegatingActionProxy,通过代理类调用getBean(beanName,Action.Class)方法,将path的名称"/login"传入,到IOC中找到对应name的Action(即,LoginAction类(在applicationContext-action.xml中配置过了,如图(3)))
第二种方案集成原理:Struts的Action交给Spring创建;
将业务逻辑对象通过spring注入到Action中,从而避免了在Action类中的直接代码查询
(客户端请求---->代理action--->取得BeanFactory--->getBean(..)创建action示例--->执行exctute方法)
4,代码示例
简单登录例子
只是Spring配置文件和Struts配置文件,以及LoginAction.java有所变动,其他代码参考Struts1.X与Spring集成——第一种方案
struts-config.xml配置文件:配置代理Action及ActionForm
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"> <struts-config> <!--生命ActionForm(即,告诉Struts哪个是ActionForm) --> <form-beans> <form-bean name="loginForm" type="com.bjpowernode.usermgr.web.forms.loginActionForm"/> </form-beans> <!-- 描述Action --> <!-- 描述Action --> <action-mappings> <action path="/login" type="org.springframework.web.struts.DelegatingActionProxy" name="loginForm" scope="request"> <!-- 转向信息 --> <forward name="success" path="/login_success.jsp"/> </action> </action-mappings> <message-resources parameter="MessageResources" /> </struts-config>
applicationContext-beans.xml配置文件:配置业务逻辑对象
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <!-- 这个IOC容器核心是个工厂,抽象工厂 --> <bean id="userManager" class="com.bjpowernode.usermgr.manager.UserMangerImpl"/> </beans>
applicationContext-action.xml配置文件:配置Struts的Action
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <!-- 配置Struts的Action --> <bean name="/login" class="com.bjpowernode.usermgr.web.actions.LoginAction" scope="prototype"> <property name="userManager" ref="userManager"/> </bean> </beans>
5,运行
6,总结
第一种方案原理:在Action中取得BeanFactory,通过BeanFactory取得业务逻辑对象——依赖查找;
第二种方案原理:将Struts的Action交给Spring创建,这样业务逻辑对象将会被注入——依赖注入;
两者区别及优缺点:
第一种是依赖查找,因为要查找依赖对象,所以要依赖Spring服务才能找到,这样就依赖了Spring服务,如果脱离了Spring,Action对象不能单独使用。
第二种是依赖注入,不依赖于别的服务,这样就避免了依赖查找,不用关系其他服务是如何工作的,没有侵入性,从而也使代码很清晰。
Struts1.X与Spring集成——第二种方案