AOP是一种设计思想,面向切面编程,通过预编译方式和运行期动态代理方式实现在不修改源代码的情况下给程序动态添加额外功能的一种技术
将非核心逻辑剥离出来以后,封装这些非核心逻辑的类、对象、方法
为某一个对象(委托类)提供一个代理(代理类),用来控制对这个对象的访问。委托类和代理类有一个共同的父类或父接口。代理类会对请求做预处理、过滤,将请求分配给指定对象。
类似找明星经纪人而不是直接去找明星
JDK原生的实现方式,需要被代理的目标类必须实现接口。
该技术要求代理对象和目标对象实现同样的接口
例子:
动态代理通过Proxy类调用newInstance方法生成某个对象的代理对象,其中使用到三个参数:
我们可以很明显的看到:
与静态代理不同的是,我们不需要自己编写代理类,这是动态生成的
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>5.3.18version>
dependency>
<aop:aspectj-autoproxy />
开启基于注解的AOP
在切面中,需要通过指定的注解将方法表示为通知方法。
通过@Order( value)
来设置优先级,value默认值是Integer的最大值,只要我们设置的数字比默认值小,它的优先级就比较高
声明式事务是建立在 AOP 之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况“提交”或者“回滚”事务。
编程式事务:
@Service
public class TransactionExample {
/** 1、获取 PlatformTransactionManager 对象 **/
@Autowired
private PlatformTransactionManager platformTransactionManager;
public void addUser() {
// 2、获取默认事务定义
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// 设置事务传播行为
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// 3、根据事务定义对象设置的属性,获取事务状态
TransactionStatus status = platformTransactionManager.getTransaction(def);
try {
// 4、执行业务代码(这里进行模拟,执行多个数据库操作方法)
userMapper.delete(1);
userMapper.delete(2);
// 5、事务进行提交
platformTransactionManager.commit(status);
} catch(Exception e){
// 5、事务进行回滚
platformTransactionManager.rollback(status);
}
}
}
以前我们学的事务的管理分散在代码的四处,复用性不高。而且每一次都需要自己完成代码的编写
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
使用@Transactional注解所标识的方法或类中所有的方法使用事务进行管理
transaction-manager属性设置事务管理器的id。当bean的id为transactionManager
时也可以不设置。
小结:
声明式事务的配置步骤:
在Spring的配置文件中配置事务管理器
开启事务的注解驱动
在需要被事务管理的方法(或类)上,添加@Transactional注解,该方法就会被事务管理。
@Transactional注解标识的位置
- 标识在方法上
- 标识在类上,则类中所有的方法都会被事务管理
只读属性 readonly
&& 事务超时属性 timeout
在发生异常时,发生事务回滚。经了解,只有未检查异常可以导致事务回滚(RuntimeException和Error类型的异常),受检查异常不会。
隔离级别在学习数据库中已经提到:
上图源网络。
有一个例子:
有一个人要买两本书,但是他的钱只能买一本。此时我们有两个业务:买书和结账。如果结账是一个事务的话,这个人的操作就会失败—一本书也买不到。但是我们明明可以先只买一本,此时就要求我们把买书看成一个事务。那么如何操作呢?
通过@Transactional中的propagation属性设置事务传播行为
在BookServiceImpl中的buyBook()上面,注解@Transactional的propagation属性