Spring事务管理难点剖析

来源:互联网 发布:股票首日上市价格算法 编辑:程序博客网 时间:2024/04/29 14:28

1:使用Spring是否一定要使用Spring事务管理器。

      答:不一定,没有事务管理器也可以使用Spring jdbc 和ORM等持久化技术,因为默认情况下,数据源autoCommit设置为true。所以所有通过jdbcTemplate执行的语句马上提交,没有事务。而一旦设置为false则在访问数据的时候可能抛出异常。

2:Spring事务方法嵌套调用的问题。

      答:Spring事务传播机制是Spring凭借自身的框架提供的功能,并且总共支持一下7中事务传播行为。PROPAGATION_REQUIRED,PROPAGATION_SUPPORTS,PROPAGATION_MANDATORY,PROPAGATION_REQUIRES_NEW,       PROPAGATION_NOT_SUPOPORTED, PROPAGATION_NEVER,PROPAGATION_NESTED.其中PROPAGATION_REQUIRED是其默认的传播行为。具体的含义请自行查询。

3:Spring事务方法多线程困惑。

      答:我们知道Web容器本身就是多线程的,Web容器为一个HTTP请求创建一个独立的线程(一般的都是线程池),所以有此请求所牵涉到的Spring容器中的Bean也是运行于多线程的环境下。在绝大多数情况下,Spring的Bean都是单实例的,单实例Bean最大的好处就是县城无关性,不存在多线程并发访问的问题,也就是线程安全的。一个类能够以单实例的方法运行的前提是“无状态”:即一个类不能拥有状态变化的成员变量。我们知道,在传统的编程中,DAO必须持有一个Connnection,而Connection即使状态变化的对象。所以传统的DAO不能做成单实例的,每次要用时必须创建一个新的实例。传统的Service由于内部包含了若干个有状态的Dao成员变量,所以其本身也是有状态的。但是Spring中,DAO和Service都以单实例的方式存在。Spring是通过ThreadLocal将有状态的变量本地线程化,达到另一个层面上的“线程无关”,从而实现线程安全。Spring不遗余力地将有状态的对象无状态化,就是要达到单实例化Bean的目的。由于Spring已经通过ThreadLocal的设施将Bean无状态化,所以Spring中单实例Bean对线程安全问题拥有了一种天生的免疫能力。不但单实例的Service可以成功运行于多线程环境中,Service本身还可以自由地启动独立线程以执行其他的Service。基于以上的原理,我们可以得出结论:在相同线程中进行相互嵌套调用的事务方法工作于相同的事务中。如果这些相互嵌套的方法工作于不同的线程中,则不同线程下的事务方法工作在独立的事务中。

4:持久层混合使用问题。

    答:对于Hiberate+Spring jdbc在同一事务中混合使用的情况,我们可以得出如下结论:由于hiberate存在一级和二级缓存问题所以,混合使用将会存在“事务同步而缓存不同步”的情况,所以需要显示调用hebernate的flush方法。因此我们建议最好用Hibernate进行读写操作而只使用Spring jdbc进行读操作。

5:不能进行动态代理的方法有哪些。

    答:Spring中使用的是运行期的动态代理,有两种,一种是jdk的动态代理,接口代理。一种是基于CGLIB的动态代理,子类代理。对于第一种如果接口中的方法是public static则该方法不能进行代理,对于第二种,由于是子类进行代理,所以被final,static,private等修饰符修饰的方法不可被代理。

6:持久层数据连接泄露问题。

    答:如果我们使用框架给我们提供的模板类进行操作则不会存在连接泄露问题,如果是在程序中自己从连接池私自获取的数据连接,则会发生数据连接泄露问题。例如:jdbcTemplate.getDateSource().getConnection()私自从连接池获取连接就会发生泄露问题。而模板类中是通过DataSourceUtils.getConnection(getDataSource)获取连接并且最后还通过DataSourceUtils.releaseConnection(con,getDataSource())来进行连接的释放,则是不会发生泄露问题。


0 0
原创粉丝点击