一、AOP(面向切面编程)
1.1 AOP简介
AOP,全称Aspect-Oriented Programming,即面向切面编程,是一种编程范式,其主要目标是提高编程的可复用性和模块化。AOP通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
1.2 AOP的主要概念
aspect: 切面,切面有切点和通知组成,即包括横切逻辑的定义也包括连接点的定义
pointcut: 切点,每个类都拥有多个连接点,可以理解是连接点的集合
joinpoint: 连接点,程序执行的某个特定位置,如某个方法调用前后等
weaving: 织入,将增强添加到目标类的具体连接点的过程
advice: 通知,是织入到目标类连接点上的一段代码,就是增强到什么地方? 增强什么内容?
target: 目标对象,通知织入的目标类
aop Proxy: 代理对象,即增强后产生的对象
- Spring AOP 底层实现,是通过JDK动态代理或CGLib代理在运行时期在对象初始化阶段织入代
JDK动态代理基于接口实现 — — 区别 ---- CGLib是基于类的继承实现
1.3 Aspect概念
Before advice
前置通知,即在目标方法调用之前执行。注意: 即无论方法是否遇到异常都执行
After returning advice
后置通知,在目标方法执行后执行,前提是目标方法没有遇到异常,如果有异常则不执行通知
After throwing advice
异常通知,在目标方法抛出异常时执行,可以获取异常信息
After finally advice
最终通知,在目标方法执行后执行,无论是否是异常执行。
Around advice
环绕通知,最强大的通知类型,可以控制目标方法的执行(通过调用ProceedingJoinPoint,proceed()),可以在目标执行全过程中进行执行。
1.4 AOP示例代码
@Aspect
public class LoggingAspect {
@Before("execution(* com.example.myapp.*.*(..))") //在myspp下的所有文件
public void logBefore(JoinPoint joinPoint) { System.out.println("The method " +joinPoint.getSignature().getName() + "() begins");
}
@After("execution(* com.example.myapp.*.*(..))")
public void logAfter(JoinPoint joinPoint) { System.out.println("The method " + joinPoint.getSignature().getName() + "() ends");
}
}
二、事务
(使用AOP的切面事务管理来实现事务控制而不是使用TRANSACTIONAL注解硬编码到业务层)
2.1 事务简介
事务是一个逻辑单位,它包含了一组对数据库的读或写操作。事务的主要目标是保证这些操作要么全部成功,要么全部失败。事务的四个主要特性是:原子性、一致性、隔离性和持久性,通常被称为ACID特性。
2.2 事务的ACID特性
- 原子性(Atomicity):事务是一个不可分割的工作单位,事务中包含的操作要么全部完成,要么全部不完成。
- 一致性(Consistency):事务必须使数据库从一个一致性状态变换到另一个一致性状态。
- 隔离性(Isolation):一个事务的执行不能被其他事务干扰。
- 持久性(Durability):一旦事务提交,则其结果就是永久性的。
2.3 事务类型
PROPAGATION_REQUIRED (propagation_required)–支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS(propagation_supports)–支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY(propagation_mandatory)–支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW(propagation_requires_new)–新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED(propagation_not_support)–以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER(propagation_never)–以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED(propagation_nested)–如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
2.4常见事务代码
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void transfer(String fromUser, String toUser, double amount) {
User from = userDao.findByName(fromUser);
User to = userDao.findByName(toUser);
from.setBalance(from.getBalance() - amount);
to.setBalance(to.getBalance() + amount);
userDao.update(from);
userDao.update(to);
}
}