首先我们要知道,SpringMVC的事物控制其实就是利用了aop的思想。
所以在开发过程中我们要知道谁是切点?谁是通知?配置切面?
在这里的切点就是我们需要进行事物控制的方法,通知在这个事物控制里面就是事物控制。然后再进行织入的过程。
接下来我们用一个转账的例子来详细解释利用xml来进行事物的控制。
准备工作:
先在pom中导入我们需要的坐标:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
建立实体类:
再创建dao层的接口和实现:
再创建service层的接口和实现:
再创建controller层:
然后在配置文件中,分别为其配置bean对象:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test01"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountDao" class="com.outlier.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="accountService" class="com.outlier.service.impl.AccountServiceImpl" >
<property name="accountDao" ref="accountDao"></property>
</bean>
通过完成上面的步骤我们已经完成了数据库的连接。
先进行验证 刚开始我们每个账户的钱都为5000
我们先执行一下controller层的main方法:
结果:
当我们在service层中:在转账方法中,这么书写:
它的运行过程为:第一个人已经把钱转出去了,但是出现了异常,程序结束运行,所以第三行代码就没执行,那么就没人收到上个人转出去的钱。所以就出现了如下问题:
所以我们要对其进行事物控制,要么一起运行成功,要么都不运行成功
接下来我们就用xml配置方式来完成事物控制。(在上面我们就已经说了用xml配置方式来完成事物控制其实就是基于aop(面向切面变成))
第一步:首先找到切点(也就是需要增强的方法)在这里就是我刚刚说的转账方法
第二步:配置好通知(增强方法)(在这个事物控制里面我们不需要自己去编写通知,只需要导入命名空间,通过别人的来完成)
第三步:织入(将切点和通知织入到一起)
第四步:测试
下面代码实例:
第一步:首先找到切点
<!-- 目标对象:内部的方法就是我们的切点-->
<bean id="accountService" class="com.outlier.service.impl.AccountServiceImpl" >
<property name="accountDao" ref="accountDao"></property>
</bean>
第二步:配置好通知(增强方法)
<!-- 配置平台事物管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 通知:事物的增强-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
在这里需要详细解释一下:首先我们先进行配置的事物的增强再配置的管理器。
我们通过引入tx命名空间来进行事物控制,首先标签<tx:advice>为父标签,然后里面的属性,id是可以随便命名的,但是属性transaction-manager是必须要存在的,因为我们在进行代码编写的时候使用的是jdbc来完成的,因此我们要用这个属性来告诉spring我们是用什么数据库来完成的,因为不同的业务需要的数据库可能不同,所以我们就需要在这里声明,然后我们再配置上面的事物管理器(jdbc对应的管理器就是DataSource)里面需要进行dataSource的注入,因为我们在执行jdbc的时候首先需要一个连接connection,这个注入就是为了拿到刚才的连接。
接下来是它的子标签:<tx:attributes>,顾名思义就是它的属性,设置事物的属性信息的(在这个标签里面可以配置多个<tx:method />标签)。里面的标签:
<tx:method />表示的是哪些方法需要增强(也就是需要事物控制),然后*代表的是全选的意思。在<tx:method />中还有很多的其他属性,你不书写的时候那些属性都有默认值。
上面的那个代表的意思就是需要增强的方法是transfer,第二个属性表示的是隔离级别,第三个代表的是传播行为,第三个代表的是只读。
第三步:织入
<!-- 配置事物的织入-->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.outlier.service.impl.*.*(..))"/>
</aop:config>
第四步:测试(最开始每人还是5000)
经运行结果:
就完成了事物控制。