代理模式及其在spring与struts2中的体现
来源:互联网 发布:java怎么固定gui位置 编辑:程序博客网 时间:2024/04/27 10:33
代理模式
代理模式有三个角色组成:
1.抽象主题角色:声明了真实主题和代理主题的共同接口。
2.代理主题角色:内部包含对真实主题的引用,并且提供和真实主题角色相同的接口。
3.真实主题角色:定义真实的对象。
我们先来看传统方式下一个Proxy的实现实例。
假设我们有一个UserDAO接口及其实现类UserDAOImp:
UserDAO.java:
public interface UserDAO {
public void saveUser(User user);
}
UserDAOImp.java:
public class UserDAOImp implements UserDAO{
public void saveUser(User user) {
……
}
}
如果我们希望在UserDAOImp.saveUser方法执行前后追加一些处理过程,如启动/
提交事务,而不影响外部代码的调用逻辑,那么,增加一个Proxy类是个不错的选择:
UserDAOProxy.java
public class UserDAOProxy implements UserDAO {
private UserDAO userDAO;
public UserDAOProxy(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void saveUser(User user) {
UserTransaction tx = null;
try {
tx = (UserTransaction) ( new InitialContext().lookup("java/tx") );
userDAO.saveUser(user);
tx.commit();
} catch (Exception ex) {
if (null!=tx){
try {
tx.rollback();
}catch(Exception e) {
}
}
}
}
}
UserDAOProxy同样是UserDAO接口的实现,对于调用者而言,saveUser方法的使
用完全相同,不同的是内部实现机制已经发生了一些变化――我们在UserDAOProxy中为
UserDAO.saveUser方法套上了一个JTA事务管理的外壳。
上面是静态Proxy模式的一个典型实现。
现在假设系统中有20个类似的接口,针对每个接口实现一个Proxy,实在是个繁琐无
味的苦力工程。
动态代理
Dynamic Proxy的出现,为这个问题提供了一个更加聪明的解决方案。
我们来看看怎样通过Dynamic Proxy解决上面的问题:
public class TxHandler implements InvocationHandler {
private Object originalObject;
public Object bind(Object obj) {
this.originalObject = obj;
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
if (!method.getName().startsWith("save")) {
UserTransaction tx = null;
try {
tx = (UserTransaction) ( new InitialContext().lookup("java/tx") );
result = method.invoke(originalObject, args);
tx.commit();
} catch (Exception ex) {
if (null != tx) {
try {
tx.rollback();
} catch (Exception e) {
}
}
}
} else {
result = method.invoke(originalObject, args);
}
return result;
}
}
首先注意到,上面这段代码中,并没有出现与具体应用层相关的接口或者类引用。也就
是说,这个代理类适用于所有接口的实现。
其中的关键在两个部分:
1.
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), this);
java.lang.reflect.Proxy.newProxyInstance方法根据传入的接口类型
(obj.getClass().getInterfaces()) 动态构造一个代理类实例返回, 这个代理类是JVM
在内存中动态构造的动态类,它实现了传入的接口列表中所包含的所有接口。
2
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
……
result = method.invoke(originalObject, args);
……
return result;
}
InvocationHandler.invoke方法将在被代理类的方法被调用之前触发。通过这个方
法中,我们可以在被代理类方法调用的前后进行一些处理,如代码中所示,
InvocationHandler.invoke方法的参数中传递了当前被调用的方法(Method) ,以及被
调用方法的参数。
同时,我们可以通过Method.invoke方法调用被代理类的原始方法实现。这样,我们
就可以在被代理类的方法调用前后大做文章。
在示例代码中,我们为所有名称以“save”开头的方法追加了JTA事务管理。
Spring中AOP实现
其中最典型的就是Spring中的配置化事务管理,先看一个例子
<beans>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName">
<value>org.gjt.mm.mysql.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/sample</value>
</property>
<property name="username">
<value>user</value>
</property>
<property name="password">
<value>mypass</value>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>
<bean id="userDAO" class="net.xiaxin.dao.UserDAO">
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>
<bean id="userDAOProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="target">
<ref local="userDAO" />
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="get*">
PROPAGATION_REQUIRED,readOnly
</prop>
</props>
</property>
</bean>
</beans>
看看例子当中的userDAOProxy,想必大家已经猜测到Spring事务管理机制的实现原理。
是的,只需通过一个Dynamic Proxy对所有需要事务管理的Bean进行加载,并根据配
置,在invoke方法中对当前调用的方法名进行判定,并为其加上合适的事务管理代码,那
么就实现了Spring式的事务管理。
当然,Spring中的AOP实现更为复杂和灵活,不过基本原理一致。
Stuts2中的AOP实现
拦截器是Strut2的一个重要组成部分,对于Strut2框架而言,可以将其理解为一个空的容器,正是大量的内建拦截器完成该框架的大部分操作。比如,params拦截器将http请求中的参数解析出来,设置成action的属性;servlet-config直接将http请求中的httpServletRequest实例和httpServletRespon实例传给action;fileUpload拦截器负责解析请求当中的文件域,并将文件域设置为action的属性。。。。。。
对于Strut2的拦截器体系而言,当我们需要某个拦截器的时候,只需要在配置文件中应用该拦截器即可,反之亦然。不管是否应用某个拦截器,对于整个Strut2框架都不会影响,这种设计哲学,是一种可插拔的设计,具有非常好的可扩展性。
Strut2中的拦截器体系是一种AOP设计哲学,它允许开发人员以一种简单的方式来进行AOP方式的开发。
下面以一个例子来介绍Strut2中的AOP。
使用拦截器完成权限控制
l 实现拦截器
大部分web应用都涉及权限控制,当浏览者需要执行某个操作时,应用需要先检查浏览者是否登录,以及是否有足够的权限来执行该操作。
本示例要求用户登录,必须为制定用户名才可以查看系统中某个视图资源,否则直接转入登录页面。对于上面的需求,可以在每个action执行业务逻辑之前,先执行权限检查逻辑,但这种做法不利于代码复用。因为大部分action中检查权限代码都大同小异,故将这些代码逻辑放在拦截器中,将会更加优雅。
检查用户是否登录,通常都是跟踪用户的Session来完成的,通过ActionContext即可访问到Session中的属性,拦截器的intercep(ActionInvocation invocation)方法的invocation参数可以很轻易的访问到请求相关的ActionContex实例。
//权限检查拦截器继承AbstractIntercept
Public class AuthorityInterceptor extends AbstractInterceptor{
//拦截action处理的拦截方法
Public String intercept(ActionInvocation invocation){
//取得请求相关的ActionContex实例
ActionContext ctx = invocation.getInvocationContext();
Map session = ctx.getSession();
//取出名为user的session属性
String user = (String)session.get(“User”);
If(user !=null && user.equals(“scott”) ){
Return invocation.invoke();
}
Ctx.put(“tip”,”您还没有登录,请输入scott、tiger登录”);
Return Action.Login;
}
上面的拦截器代码非常简单,先从ActionInvocation 取得用户的session实例,然后从中取出user属性,通过判断属性值确定用户是否登录,从而判断是否转入登录页面。
l 配置拦截器
一旦实现了拦截器,就可以在所有需要实现权限控制的action中复用上面的拦截器。
为了使用拦截器,首先需要在struts.xml文件中定义该拦截器,定义拦截器的配置片段如下:
<interceptors>
<interceptor name=”authority” class=”qj.AuthorityInterceptor” />
</interceptors>
定义了拦截器后,可以在action中应用该拦截器,应用拦截器的配置片段如下:
<action name=”viewBook”>
<result>/WEB-INF/jsp/viewBook.jsp</result>
<interceptor-ref name=”defaultStack” />
<interceptor-ref name=”authority” />
</action>
这种通过拦截器控制权限的方式,显然具有更好的代码复用。
如果为了简化struts.xml文件的配置,避免在每个action中重复配置该拦截器,可以将该拦截器配置成一个默认拦截器栈。
参考资料:http://blog.csdn.net/qiuleng2002/article/details/5776814
- 代理模式及其在spring与struts2中的体现
- 代理模式及其在spring与struts2中的体现
- 代理模式及其在spring与struts2中的体现
- 动态代理及其在Spring中的应用
- 设计模式在buiw中的体现
- Reactor模式及在DSS中的体现
- Reactor模式及在DSS中的体现
- Reactor模式及在DSS中的体现
- Spring中的代理模式
- 代理模式与Spring
- java代理模式的体现
- java中的代理模式与spring中的AOP
- 部分JAVA设计模式在Android中的体现。
- 设计模式中关系在代码中的体现
- 【设计模式】-几种关系在代码中的体现
- Spring AOP中的代理模式
- 信号量在linux0.11下的实现及其在生产者,消费者应用中的体现
- 在JavaScript中的代理模式
- Android推送方案分析(MQTT/XMPP/GCM)
- java的HashMap和ArrayList比较器
- 细说智能卡加密狗
- 动态展示Google map
- maven初步
- 代理模式及其在spring与struts2中的体现
- HTTP Live Streaming直播(iOS直播)技术分析与实现
- 二分图最大匹配:匈牙利算法(poj3041)
- 高通AR增强现实Unity3D
- Mac兼容NTFS插件内含破解文件
- Nginx+Tomcat实现反向代理与动静分离
- VC 中与字符串相关的宏 _T、TEXT,_TEXT、L 的作用
- main() 函数解释
- cocos2d-x 编写Android.mk中的LOCAL_SRC_FILES的终极技巧