JAVAEE之Spring学习(三)---通过aop切面实现事务处理
来源:互联网 发布:吉大动物医学就业知乎 编辑:程序博客网 时间:2024/06/18 18:52
需求:通过切面给项目中的service添加事务处理,让数据库表1添加用户失败后回滚,表2无法添加数据
思想:通过aop切面拦截service下的reg()方法,在拦截之前开启事务再进行dao调用,进行事务处理
需要注意的地方:在spring方式下获得到的datasource中的getconnection方法还没有进行拦截,在dao层,是通过queryrunner自动调用getconnection()进行提交,所以要将getconnection()做成单线程形式
service:
package cn.hncu.stud.service;import java.sql.SQLException;import cn.hncu.stud.dao.IStudaoa;import cn.hncu.stud.domain.User;public class serviceimpl implements IStudentService { IStudaoa dao1 = null; IStudaoa dao2 = null; public IStudaoa getDao1() { return dao1; } public void setDao1(IStudaoa dao1) { this.dao1 = dao1; } public IStudaoa getDao2() { return dao2; } public void setDao2(IStudaoa dao2) { this.dao2 = dao2; } // 注入 @Override public void reg(User user) throws SQLException { dao1.reg(user); dao2.reg(user); }}
web.xml:将Spring容器放入servletContext中
<?xml version="1.0" encoding="UTF-8"?><web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name></display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value> <!-- 如果有路径要用"/"开始 --> classpath:beans.xml, /WEB-INF/applicationContext.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>StudServlet</servlet-name> <servlet-class>cn.hncu.stud.servlet.StudServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>StudServlet</servlet-name> <url-pattern>/StudServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list></web-app>
servlet:通过ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext());获取spring容器
package cn.hncu.stud.servlet;import java.io.IOException;import java.io.PrintWriter;import java.sql.SQLException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.support.WebApplicationContextUtils;import cn.hncu.stud.domain.User;import cn.hncu.stud.service.IStudentService;public class StudServlet extends HttpServlet { private IStudentService service = null; @Override public void init() throws ServletException { // 获取web项目中的spring容器 ApplicationContext ctx = WebApplicationContextUtils .getWebApplicationContext(getServletContext()); service = ctx.getBean("service", IStudentService.class); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); User user = new User(); user.setName(name); try { service.reg(user); request.getSession().setAttribute("user", user); request.getRequestDispatcher("/jsps/show.jsp").forward(request, response); } catch (SQLException e) { e.printStackTrace(); } }}
applicationContext:用于配置dataSource和拦截getconnection的公共Spring容器配置文件
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> </bean> <!-- 切面=切点+通知 --> <bean id="advisor" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor"> <!-- 切点 --> <property name="expression"> <value> execution( void cn.hncu.stud..serviceimpl.reg(..) ) </value> </property> <property name="advice"> <bean class="cn.hncu.stud.utils.AroundAdvice"> <property name="data" ref="dataSource"></property> </bean> </property> </bean> <!-- 切面=切点+通知 --> <bean id="advisor1" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor"> <!-- 切点 --> <property name="expression"> <value>execution(* *..*.getConnection()) </value> </property> <property name="advice"> <bean class="cn.hncu.stud.utils.ConAdvice"> </bean> </property> </bean> <context:property-placeholder location="WEB-INF/conf/jdbc.properties" /> <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> <property name="driverClass" value="${driver}"> </property> <property name="url" value="${url}"></property> <!-- ${username}是系统默认的变量--> <property name="username" value="${uname}"></property> <property name="password" value="${password}"></property> </bean></beans>
用于拦截getconnection方法的切面:
package cn.hncu.stud.utils;import java.lang.reflect.Method;import java.sql.Connection;import javax.sql.DataSource;import net.sf.cglib.proxy.Callback;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodProxy;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;public class ConAdvice implements MethodInterceptor { private ThreadLocal<Connection> t1 = new ThreadLocal<Connection>(); DataSource data = null; public DataSource getData() { return data; } public void setData(DataSource data) { this.data = data; } @Override public Object invoke(MethodInvocation inv) throws Throwable { Connection con = t1.get(); if (con == null) { // 往本地线程池中放一个被屏蔽掉close()方法的con对象 final Connection con0 = ((Connection) inv.proceed());// 当前被拦截的是getconnection返回的是一个con // 对con0进行代理(屏蔽close()) Callback callback = new net.sf.cglib.proxy.MethodInterceptor() { @Override public Object intercept(Object proxiedObj, Method method, Object[] args, MethodProxy proxy) throws Throwable { if (method.getName().equals("close")) { return null; } return method.invoke(con0, args); } }; // 生成代理后的对象 con = (Connection) Enhancer.create(Connection.class, callback); t1.set(con);// 把代理后的对象放进去 } return con; }}
beans.xml:用于配置stud模块下的类的关联
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="studDao" class="cn.hncu.stud.dao.IStuJDBCDAO"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="studDao2" class="cn.hncu.stud.dao.IStuJDBCDAO2"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="service" class="cn.hncu.stud.service.serviceimpl"> <property name="dao1" ref="studDao"></property> <property name="dao2" ref="studDao2"></property> </bean></beans>
AroundAdvice:进行service类的拦截:
package cn.hncu.stud.utils;import java.sql.Connection;import javax.sql.DataSource;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;public class AroundAdvice implements MethodInterceptor, ApplicationContextAware { ApplicationContext ctx = null; DataSource data = null; public DataSource getData() { return data; } public void setData(DataSource data) { this.data = data; } @Override public Object invoke(MethodInvocation invocation) throws Throwable { Connection con = data.getConnection(); con.setAutoCommit(false); System.out.println("开启事务"); // 放行 try { Object returnValue = invocation.proceed(); con.commit(); return returnValue; } catch (Exception e) { con.rollback(); System.out.println("事务回滚"); } finally { con.setAutoCommit(true); } return null; } @Override public void setApplicationContext(ApplicationContext ctx) throws BeansException { this.ctx = ctx; }}
这样就成功通过spring实现数据库的事务处理
阅读全文
0 0
- JAVAEE之Spring学习(三)---通过aop切面实现事务处理
- JAVAEE之Spring学习(三)---aop切面(一)
- JAVAEE之Spring学习(四)---通过spring注解进行事务处理
- Spring-通过xml配置文件实现切面(AOP)
- Spring 切面 AOP基础 之三
- Spring之面向切面编程AOP(三)
- Spring之AOP实现面向切面编程
- Spring AOP 之 实现切点、切面
- Spring AOP之切面
- Spring AOP(三)——通过@AspectJ注解切面
- Spring学习笔记 —— AOP(面向切面编程) 之使用ProxyFactoryBean实现AOP
- Spring 通过注解方式实现AOP切面编程
- Spring学习笔记(三)--面向切面编程AoP
- Spring学习三(AOP面向切面编程)
- Spring AOP切面实现:示例
- Spring AOP切面实现:解析
- spring之Aop面向切面
- Spring之AOP面向切面编程实现(一)
- 【stm32f103】USART RX实现(寄存器版)
- 真正理解 git fetch, git pull 以及 FETCH_HEAD
- Spring编程<六>
- GCD & LCM (数学基础)
- 登录验证码的制作!
- JAVAEE之Spring学习(三)---通过aop切面实现事务处理
- js字符操作
- Github 使用 与 Git的链接
- graphviz在linux上的中文乱码问题解决办法
- 《head_first_html_learnning》
- 成为Java顶尖程序员 ,看这11本书就够了
- Android系统休眠机制和doze模式的关系
- xpath , 抽取字段常见error
- android炫酷动画源码,QQ菜单、瀑布流、二维码源码