`
yiminghe
  • 浏览: 1431569 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

利用aop重构数据访问层

    博客分类:
  • java
阅读更多

由于一直以来小项目做的多,造成了轻后端重前端的恶果,结果后端现在还在使用陈旧的jsp,数据访问层重复代码也不少,近来看了下 spring in action决定对这一部分进行一些修改


1。原先架构


每个模块一个类,层层继承,形成模块功能链

public class Module {
    public void actionA(){}
    public void actionC(){}
.....
}
public class ModuleA extend Module{

      public void actionA(){
            Connection con=DB.getConnection();
            try{
            }catch(....){
              logger.error(...);
            }finally{
                  con.close();
            }
      }
      //other actions
}

public class ModuleB  extends ModuleA{
      public void actionB(){
      }
      //other actions 
}

 调用时,只需调用ModuleB的操作(继承最低层功能类,包含所有操作),

 

Module getModule() {
   return new ModuleB();
}

getModule().action..(...);
 

 

一方面connection处理在各个方法冗余,另一方面那么当新增加模块时,有两个选择


1.三处源代码修改

public class Module {
   //added action
}
public class ModuleC  extends ModuleB{
      public void actionC(){
      }
      //other actions 
}

Module getModule() {
   return new ModuleC();
}

2.还是三处源代码修改

public class Module {
   //added action
}

public class ModuleB  extends ModuleC{
      public void actionB(){
      }
      //other actions 
}

public class ModuleC  extends ModuleA{
      public void actionC(){
      }
      //other actions 
}

即关键为维护链状继承结构。


2.利用aop重构

利用spring的aop特性将connection创建过程抽离出来,利用aop前置将connection先创建出来保存在模块中,后置销毁成员变量connection。

 

1.首先修改基类,将连接做为成员变量:

public class Module {
    private Connection con;
    public void setConnection(Connection con){this.con=con;}
    public Connection getConnection(){return this.con;}

    public void actionA(){}
    // .. other actions
}

 

其他模块数据库操作改变

 

public class ModuleA extends Module{

      public void actionA(){
            Connection con=this.getConnection();
            //.. 数据库操作
            //不用关闭,不用处理异常
      }
      //other action
}


在各个模块的操作中,不用关闭连接,也不用处理异常 ,将这些功能切面独立出来


2.创建 aspect

 

2.1 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"
	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">

	<bean id="Op" class="ModuleB"  scope="prototype"/>
	
	<bean id="DbOp" class="DbOp" />
	<aop:config>
		<aop:aspect ref="DbOp">
			<aop:pointcut id="DbOpPointcut"
				expression="execution(* Module*.action*(..)) and target(bean)" />
			<aop:before method="prepareConnection" pointcut-ref="DbOpPointcut"
				arg-names="bean" />
			<aop:after-returning method="closeConnection"
				pointcut-ref="DbOpPointcut" arg-names="bean" />

			<aop:after-throwing method="exceptionHandle"
				pointcut-ref="DbOpPointcut" arg-names="bean" />

		</aop:aspect>
	</aop:config>

</beans>

其中Op指向继承最低层的模块对象(包含所有模块操作),对 Module*类的action*方法创建pointcut,并且给advise传递target参数,即module功能对象。


2.2 aspect

public class DbOp {
	
	static Logger logger = Logger.getLogger(DbOp.class);
	public void prepareConnection(Module impl) throws SQLException {
		Connection con = null;
		con =DB.getConnection();
		impl.setConnection(con);
		logger.info("prepareConnection");
	}

	public void closeConnection(Module impl) throws SQLException {
		Connection con = impl.getConnection();
		con.close();
		con = null;
		impl.setConnection(con);
		logger.info("closeConnection");
	}

	public void exceptionHandle(Module impl) {
		Connection con = impl.getConnection();
		if (con != null) {
			try {
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			con = null;
			impl.setConnection(con);
		}
		logger.info("exceptionHandle");
	}

}
 

将创建连接,销毁连接,异常处理分离开,并将连接保存到模块功能对象 即可。


3.最后改变获取模块功能对象的方式

 

ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
Module getModule(){
    return (Module)ctx.get("Op");
}
 

这样的话以后添加新的模块,只需更改两处源码:

 

public class Module {
   //added action
}

public class ModuleC  extends ModuleB{
      public void actionB(){
      }
      //other actions 
}

 

以及一处xml配置即可:

 

<bean id="Op" class="ModuleC"  scope="prototype"/>


且代码更清晰易懂。

 

 

0
1
分享到:
评论
1 楼 hanqunfeng 2010-02-27  
既然用了spring,为什么不直接使用数据库模板类来处理dao层。

相关推荐

Global site tag (gtag.js) - Google Analytics