【框架】[Spring] 基于Spring框架的Web应用演示(附带cglib工具进行动态代理)(2)

简介: 【框架】[Spring] 基于Spring框架的Web应用演示(附带cglib工具进行动态代理)

事务

如果只代理到上面这里,写con.close方法其实会出问题的。

当然,本例很简单,servlet只请求了一个service中的一个方法,这样写没什么问题,

但是,假如我有多个service和一个service有多个方法,需要被一个用户请求servlet时同时调用时,这个连接就不能被关闭了。

因为Spring容器的事务机制的实质是对传统JDBC的封装,也即是Spring事务管理无论是对单数据库实例还是分布式数据库实例,要实现事务管理,那么必须保证在一个事务过程获得Connetion对象是同一个。

假如是servlet调用多个service或service中多个方法,需要实现的是同一个事务,我们可以:在service中写一个综合方法,在其中调用其它方法,然后给综合方法设置代理,因为这个综合方法在这里就是一个业务

,多个service,原理一样。

AOP拦截getConnection()方法,cglib工具进行动态代理Connection

然后再拦截Connection的close方法!

package cn.hncu.utils;
import java.lang.reflect.Method;
import java.sql.Connection;
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 CloseAdvice implements MethodInterceptor{
    private ThreadLocal<Object> t = new ThreadLocal<Object>();
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Object obj = t.get();
        if(obj==null){
            final Object con = invocation.proceed();//返回原型对象Connection
            //通过cglib工具进行动态代理
            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;
                    }
                    //con为原型Connection对象
                    return method.invoke(con, args);
                }
            };
            //obj为cglib工具代理后的Connection对象
            obj=Enhancer.create(Connection.class, callback);
            t.set(obj);
        }
        return obj;
    }
}

在applicationContext.xml中配置拦截getConnection()

<bean id="conClose" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
       <property name="expression" value="execution( * *..*.*.getConnection() )"></property>
       <property name="advice">
            <bean id="advice" class="cn.hncu.utils.CloseAdvice"></bean>
       </property>
    </bean>

接下来就是要用到AOP了,拦截事务。

拦截service层的。

拦截事务的切面配置:

<!-- 自动代理 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
    <!-- 事务  切面=切点+通知 -->
    <bean id="tx" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <!-- 拦截cn.hncu包下的,方法名最后为Service的任意返回值任意参数的方法 -->
        <property name="expression" value="execution (* cn.hncu..*Service.*(..) )">
        </property>
        <property name="advice">
            <bean class="cn.hncu.utils.TxAdvice"></bean>
        </property>
    </bean>

DAO层的实现类代码:

stud的实现类:

package cn.hncu.stud.dao;
import java.sql.SQLException;
import java.util.UUID;
import javax.sql.DataSource;
import org.apache.commons.dbutils.QueryRunner;
import cn.hncu.stud.domain.Book;
import cn.hncu.stud.domain.Stud;
public class StudDaoJdbc implements StudDAO{
    private DataSource dataSource = null;//依赖注入
    public DataSource getDataSource() {
        return dataSource;
    }
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    @Override
    public void saveStud(Stud stud) throws SQLException {
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        stud.setS_id(uuid);
        QueryRunner run = new QueryRunner(dataSource);
        run.update("insert into stud(s_id,s_name) values(?,?)", stud.getS_id(),stud.getS_name());
    }
}

book的实现类

package cn.hncu.stud.dao;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbutils.QueryRunner;
import cn.hncu.stud.domain.Book;
public class BookDaoJdbc implements BookDAO{
    private DataSource dataSource = null;//依赖注入
    public DataSource getDataSource() {
        return dataSource;
    }
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    @Override
    public void saveBook(Book book) throws SQLException {
        QueryRunner run = new QueryRunner(dataSource);
        run.update("insert into book(b_name) values(?)", book.getB_name());
    }
}

测试:

打开页面输入:

image.png

点按钮提交:

image.png

service:cn.hncu.stud.service.SaveServiceImpl@4adeee3d这个输出是我在servlet中测试一个错误的时候的输出。

再看数据库的数据:

image.png

image.png

然后,我们来测试下,事务回滚情况:

因为service层是:

@Override
    public void saveStudAndBook(Stud stud, Book book) throws SQLException {
        studDao.saveStud(stud);
        bookDao.saveBook(book);
    }

后调用bookDao的,所以,我们让saveBook挂了,改一下saveBook的方法中sql语句为:

image.png

这样,后面Book的存储肯定是出问题的。

再来测试:

image.png

点添加。

image.png

可以看到事务回滚了,但是看这里没用,我们去看下stud和book表有没有存储。当然book表肯定是不会被存储的,去看stud表就可以了:

image.png

可以看到,李四这个用户并没有被保存,证明事务起作用了。

完整项目源码链接:

–>点击访问本系列源码–

目录
相关文章
|
XML Java 应用服务中间件
【框架】[Spring] 基于Spring框架的Web应用演示(附带cglib工具进行动态代理)(1)
【框架】[Spring] 基于Spring框架的Web应用演示(附带cglib工具进行动态代理)
100 0
【框架】[Spring] 基于Spring框架的Web应用演示(附带cglib工具进行动态代理)(1)
|
XML 移动开发 前端开发
SpringBoot:Web(附带示例代码)
SpringBoot:Web(附带示例代码)
SpringBoot:Web(附带示例代码)
|
Web App开发 存储 NoSQL
一篇文章让你深透理解cookie和session,附带分布式WEB系统redis共享session方案
cookie和session有什么区别?这是一个很基础的知识点,大家可能都知道一个大概:cookie是存在客户端的,session是存储在服务端,cookie和session用来验证识别用户的登录状态,常见适用场景:用户登录,用户购物车数据等。
1937 0
|
Web App开发 Java 数据库
【框架】[Spring] 基于Spring框架的Web应用演示(附带cglib工具进行动态代理)
转载请注明出处:http://blog.csdn.net/qq_26525215 本文源自【大学之旅_谙忆的博客】 前言: Spring也差不多学了Ioc控制反转和实现AOP技术的两种方式了,分享一个学习Spring,用来入门挺好的例子。
978 0
|
Web App开发 移动开发 Linux
web server信息收集(附带plesk xday)
http://www.shodanhq.com http://www.shodanhq.com/search?q=plesklin http://packetstormsecurity.
1030 0
|
2月前
|
前端开发 Java 应用服务中间件
【JavaEE进阶】 初识Spring Web MVC
【JavaEE进阶】 初识Spring Web MVC
|
8月前
|
前端开发 Java 应用服务中间件
SpringMVC(基于Spring 的Web 层MVC 框架)--SpingMVC 执行流程--@RequestMapping的使用
SpringMVC(基于Spring 的Web 层MVC 框架)--SpingMVC 执行流程--@RequestMapping的使用
97 0
|
前端开发 Java Spring
|
前端开发 Java 应用服务中间件
Spring 全家桶之 Spring Web MVC(十)- Spring、Spring MVC 整合(下)
Spring 全家桶之 Spring Web MVC(十)- Spring、Spring MVC 整合
Spring 全家桶之 Spring Web MVC(十)- Spring、Spring MVC 整合(下)
|
前端开发 Java Maven
Spring 全家桶之 Spring Web MVC(十)- Spring、Spring MVC 整合(上)
Spring 全家桶之 Spring Web MVC(十)- Spring、Spring MVC 整合
Spring 全家桶之 Spring Web MVC(十)- Spring、Spring MVC 整合(上)