深入解读Spring Framework事务管理(第五弹:同时执行事务通知和自定义的分析通知)

来源:互联网 发布:csgom4a1皮肤知乎 编辑:程序博客网 时间:2024/06/05 05:56

应用场景

如果我们要在执行事务的同时执行一些基本的分析通知,要怎么做呢?
当我们执行updateFoo(Foo)方法时,我们希望有这样的动作:
1. 配置了分析通知的切面启动
2. 事务通知执行
3. 被添加了通知的对象的方法执行
4. 提交事务
5. 分析切面报告整个事务方法执行的准确时间

分析切面的类

分析切面的代码如下,通知的排序有Ordered接口控制:

package x.y;import org.aspectj.lang.ProceedingJoinPoint;import org.springframework.util.StopWatch;import org.springframework.core.Ordered;public class SimpleProfiler implements Ordered {    private int order;    // 控制通知的顺序    public int getOrder() {        return this.order;    }    public void setOrder(int order) {        this.order = order;    }    // 这个方法就是通知    public Object profile(ProceedingJoinPoint call) throws Throwable {        Object returnValue;        StopWatch clock = new StopWatch(getClass().getName());        try {            clock.start(call.toShortString());            returnValue = call.proceed();        } finally {            clock.stop();            System.out.println(clock.prettyPrint());        }        return returnValue;    }}

配合基于@Transactional注解的声明式事务一起使用

配置文件如下:

<?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"    xmlns:tx="http://www.springframework.org/schema/tx"    xsi:schemaLocation="        http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/tx        http://www.springframework.org/schema/tx/spring-tx.xsd        http://www.springframework.org/schema/aop        http://www.springframework.org/schema/aop/spring-aop.xsd">    <!-- 这是要被切的bean -->    <bean id="fooService" class="x.y.service.DefaultFooService"/>    <!-- 这是分析通知 -->    <bean id="profiler" class="x.y.SimpleProfiler">        <!-- 在事务通知之前执行 -->        <property name="order" __value="1"__/>    </bean>    <tx:annotation-driven transaction-manager="txManager" __order="200"__/>    <aop:config>            <!-- 这个通知会在事务通知执行时执行 -->            <aop:aspect id="profilingAspect" ref="profiler">                <aop:pointcut id="serviceMethodWithReturnValue"                        expression="execution(!void x.y..*Service.*(..))"/>                <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/>            </aop:aspect>    </aop:config>    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>        <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>        <property name="username" value="scott"/>        <property name="password" value="tiger"/>    </bean>    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property name="dataSource" ref="dataSource"/>    </bean>    <!-- 其他的<bean/>定义 --></beans>

这样配置了以后,一个叫做fooService的bean就被进行了切面分析并且在合适的顺序使用了事务切面。

配合基于AspectJ的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"    xmlns:tx="http://www.springframework.org/schema/tx"    xsi:schemaLocation="        http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/tx        http://www.springframework.org/schema/tx/spring-tx.xsd        http://www.springframework.org/schema/aop        http://www.springframework.org/schema/aop/spring-aop.xsd">    <bean id="fooService" class="x.y.service.DefaultFooService"/>    <!-- the profiling advice -->    <bean id="profiler" class="x.y.SimpleProfiler">        <!-- execute before the transactional advice (hence the lower order number) -->        __<property name="order" value="1__"/>    </bean>    <aop:config>        <aop:pointcut id="entryPointMethod" expression="execution(* x.y..*Service.*(..))"/>        <!-- will execute after the profiling advice (c.f. the order attribute) -->        <aop:advisor advice-ref="txAdvice" pointcut-ref="entryPointMethod" __order="2__"/>        <!-- order value is higher than the profiling aspect -->        <aop:aspect id="profilingAspect" ref="profiler">            <aop:pointcut id="serviceMethodWithReturnValue"                    expression="execution(!void x.y..*Service.*(..))"/>            <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/>        </aop:aspect>    </aop:config>    <tx:advice id="txAdvice" transaction-manager="txManager">        <tx:attributes>            <tx:method name="get*" read-only="true"/>            <tx:method name="*"/>        </tx:attributes>    </tx:advice>    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>        <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>        <property name="username" value="scott"/>        <property name="password" value="tiger"/>    </bean>    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property name="dataSource" ref="dataSource"/>    </bean>    <!-- 其他的<bean/>定义 --></beans>
1 0
原创粉丝点击