- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nadoutong</groupId>
<artifactId>spring_day04_annotationAOP</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
</dependencies>
</project>
- bean.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
<!--开启注解扫描-->
<context:component-scan base-package="com.nadoutong"/>
<!-- 配置jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg name="dataSource" ref="ds"></constructor-arg>
</bean>
<!-- 配置连接池-->
<bean id="ds" class="com.alibaba.druid.pool.DruidDataSource">
<!--连接数据库的ur1 -->
<property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai" />
<!--连接数据库的用户名 -->
<property name="username" value="root" />
<!--连接数据库的密码 -->
<property name="password" value="123456" />
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
</bean>
<!-- 配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"></property>
</bean>
<!-- 开启事务-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 开启aop注解支持-->
<aop:aspectj-autoproxy/>
</beans>
- service包
package com.nadoutong.service;
public interface AccountService {
void transfer(int a, int b,double money);
}
package com.nadoutong.service.impl;
import com.nadoutong.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("accountService")
//Transactional()里面可以跟 readOnly只读事务,propagation 事务的格力级别
//声明式事务:
// 声明式事务管理方法允许开发者配置的帮助下来管理事务,
// 而不需要依赖底层API进行硬编码。开发者可以只使用注解或基于配置的 XML 来管理事务。
@Transactional
public class AccountServiceImpl implements AccountService {
@Autowired
private JdbcTemplate jdbcTemplate;
public void transfer(int a,int b,double money) {
// 在mysql中获取a,b的money
String qu1="select money from user where id=?";
Double moneya = jdbcTemplate.queryForObject(qu1, Double.class, a);
Double moneyb = jdbcTemplate.queryForObject(qu1, Double.class, b);
//模拟转账
moneya-=money;
moneyb+=money;
// 修改数据库
String sql="update user set money=? where id=?";
jdbcTemplate.update(sql,moneya,a);
jdbcTemplate.update(sql,moneyb,b);
}
}
- utils包
package com.nadoutong.util;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect//表明当前类是一个切面
public class Logger {
// 定义切入点
@Pointcut("execution(* com.nadoutong.service.impl.*.*(..))")
public void pt1(){}
// @Before("pt1()")
// public void beforeadvice(){
// System.out.println("前置通知");
// }
//
// @AfterReturning("pt1()")
// public void afteradvice(){
// System.out.println("后置通知");
// }
//
// @AfterThrowing("pt1()")
// public void throwingadvice(){
// System.out.println("异常通知");
// }
// @After("pt1()")
// public void finnaladvice(){
// System.out.println("最终通知");
// }
// 环绕通知
@Around("pt1()")
public Object aroudadvice(ProceedingJoinPoint pjp){
try {
System.out.println("开始转账");
Object[] args = pjp.getArgs();
Object proceed = pjp.proceed(args);//执行业务层逻辑代码
System.out.println("成功转账");
return proceed;
} catch (Throwable throwable) {
System.out.println("转账错误,回滚事务");
throw new RuntimeException();
} finally {
System.out.println("最终通知");
}
}
}
mysql内容
- 测试
package com.nadoutong;
import com.nadoutong.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AOPTest {
@org.junit.Test
public void test01(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean.xml");
AccountService accountService=(AccountService)applicationContext.getBean("accountService");
accountService.transfer(2,3,300);
}
}
测试结果:
测试事务处理:
在serviceImpl中添加一处错误:
jdbcTemplate.update(sql,moneya,a);
int error=1/0;//错误
jdbcTemplate.update(sql,moneyb,b);
再次执行测试方法
出现错误,查看数据库
数据没有出错,说明事务配置成功