spring aop的实现方式(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cuisongliu/article/details/49150795

这里我们说说spring aop 事务处理的配置,这里有三种方式实现:
这里要注意一点,,要进行事务管理的方法,必须在方法外进行异常的抛出,这样事务管理器才能接收到,然后进行事务的回滚。如果用try-catch处理异常,将不会进行事务回滚。如果必须使用try-catch的话,必须要throw出去。
事务管理器都是使用的声明式事务处理


  • 注解实现

    1. spring.xml配置

      <bean
          id="transactionManager"     class="org.springframework.jdbc.datasource.DataSourceTransactionManager"        
          p:dataSource-ref="dataSource" />
      <tx:annotation-driven  
          transaction-manager="transactionManager"   
          proxy-target-class="true" />

      注意: proxy-target-class=”true” 看自己的需求,是针对类注入还是针对与接口注入,我的项目没有写接口所以加了这个否则这里不用写这个.

    2. 注解方式加事务

      探索@Transactional注解:
      你可以指定传播、隔离级别、超时以及允许和不允许的异常。
      @Transactional注解的属性:


      propagation:指定事务定义中使用的传播
      isolation:设定事务的隔离级别
      timeout:指定事务的超时(秒)
      readOnly:指定事务的只读性
      noRollbackFor:目标方法可抛出的异常所构成的数组,但通知仍会提交事务
      rollbackFor:异常所构成的数组,如果目标方法抛出了这些异常,通知就会回滚事务

      • 涉及到增删改都需要进行事务管理

        @Transactional
        public Map<String, Object> execCwsDayExec() throws Exception{
            //执行存储过程
            Map<String, Object> params = new HashMap<String, Object>();
            try {
                params.put("iResultCode", 0);
                params.put("iResultName","");
                sqlSession.update(super.DOMAIN_NAME+".execCwsDayExec",params);
            } catch (Exception e) {
                logger.error("执行日终存储过程发生错误:{}", e.getMessage(), e);
                throw e;//非只读事务,如果要try-catch的话,必须throw, 否则事务异常捕捉不到,事务也不会回滚.
            }
            return params;
        }
      • 查询不写事务或者只读事务都可以的

        @Transactional(readOnly=true)
        public CwsDayChange getCurrDayChange() {
            List<CwsDayChange> list=sqlSession.selectList(DOMAIN_NAME
                    + ".selectAll");
            if (list.size() > 0)
                return list.get(0);
            else
                return null;
        }

  • 使用切面管理事务

    1. spring.xml配置

      <bean id="txManager"         class="org.springframework.orm.hibernate3.HibernateTransactionManager">
          <property name="sessionFactory" ref="sessionFactory" />
      </bean>
      <aop:config>
          <aop:pointcut expression="execution(public * com.ttcity.portal.service..*.*(..))"
              id="bussinessServices" />
          <aop:advisor pointcut-ref="bussinessServices" advice-ref="txAdvice" />
      </aop:config>
      
      <tx:advice id="txAdvice" transaction-manager="txManager">
          <tx:attributes>
              <tx:method name="select*" read-only="true" />
              <tx:method name="query*" read-only="true" />
              <tx:method name="find*" read-only="true" />
              <tx:method name="get*" read-only="true" />
              <tx:method name="insert*" propagation="REQUIRED" />
              <tx:method name="add*" propagation="REQUIRED" />
              <tx:method name="save*" propagation="REQUIRED" />
              <tx:method name="modify*" propagation="REQUIRED" />
              <tx:method name="del*" propagation="REQUIRED" />
          </tx:attributes>
      </tx:advice>
    2. 配置说明

      切面的关键在于execution(public * com.ttcity.portal.service...(..))的配置,主要说所有返回值的public方法且包名前缀是com.ttcity.portal.service的进行AOP拦截加事务。


      而至于事务是只读还是非只读在于
      < tx:method name=”select*” read-only=”true” />(只读性) 和< tx:method name=”del*” propagation=”REQUIRED” />(事务性),name的主要作用是函数的前缀,这样就可以拦截切面方法且方法名为select开头的为只读事务,而del开头事务性拦截。


  • 基于SpringAOP的拦截器(主要利用BeanNameAutoProxyCreator自动创建事务代理)

        <!--声明式事务管理器 -->
        <bean id="transactionManager"       class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
        <!-- 配置一个事务拦截 -->
        <bean id="trxInterceptor"       class="org.springframework.transaction.interceptor.TransactionInterceptor">
            <property name="transactionManager" ref="transactionManager" />
            <property name="transactionAttributes">
                <props>             
                    <prop key="insert*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable</prop>
                    <prop key="del*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable</prop>
                    <prop key="add*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable</prop>                
                    <prop key="query*">PROPAGATION_SUPPORTS,readOnly</prop>
                    <prop key="select*">PROPAGATION_SUPPORTS,readOnly</prop>                
                </props>
            </property>
        </bean>
        <!-- 自动装配事务到bean -->
        <bean id="autoTrx"      class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
            <property name="beanNames">
                <list>
                    <value>*BS</value>
                </list>
            </property>
            <property name="interceptorNames">
                <list>
                    <value>trxInterceptor</value>               
                </list>
            </property>
        </bean>

    我们来说下这个配置,这个配置文件主要要关心
    < property name=”transactionAttributes”>节点,下面的props内容主要是增加哪些方法名需要进行什么样的事务处理。例如:

    <prop key="insert*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable</prop>

    是说方法名为insert开头方法进行异常事务处理如果发生异常则需要回滚。

    <prop key="query*">PROPAGATION_SUPPORTS,readOnly</prop>

    这段代码作用是以query开头方法为只读事务。


    到这里我们只知道给哪些方法加事务,但是还不知道哪个类里的方法,这里需要用到BeanNameAutoProxyCreator的相关配置,这个配置会自动装配bean:

    <property name="beanNames">
        <list>
           <value>*BS</value>
        </list>
    </property>

    这段配置作用是拦截以BS结尾的类名,这样我们自动装配bean的配置就写好了。

阅读更多

没有更多推荐了,返回首页