AOP
1.简介
Aop面向切面编程:在开发中我们不能直接对已经设计好的代码进行修改(开放-封闭原则,对扩展开放,对修改封闭),解耦
AOP的底层实现为动态代理
* Target(目标对象):代理的目标对象
* Proxy (代理):一个类被 AOP 织入增强后,就产生一个结果代理类
* Joinpoint(连接点):所谓连接点是指那些可以被拦截到的点。在spring中,这些点指的是方法,因为
spring只支持方法类型的连接点
* Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
* Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知
分类:前置通知、后置通知、异常通知、最终通知、环绕通知
* Aspect(切面):是切入点和通知(引介)的结合
* Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织
入,而AspectJ采用编译期织入和类装载期织入
2.快速入门
导入依赖
<!-- aspectj的织入(切点表达式需要用到该jar包) -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version> 1.9.9</version>
</dependency>
创建目标类和目标实现类
创建通知类
将目标类和通知类对象创建权交给spring,在spring配置中加入
<!--目标类交给IOC容器-->
<bean id="demo" class="com.esthome.DemoImp" ></bean>
<!--通知类交给IOC容器-->
<bean id="myAdvice" class="com.esthome.MyAdvice"></bean>
在spring约束中加入aop命名空间
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
在spring.xml中配置切面
<aop:config> <!--配置aop-->
<!--抽取切点名-->
<aop:pointcut id="myPointcut" expression="execution(public void com.esthome.DemoImp.m())"/>
<!--引入通知类-->
<aop:aspect ref="myAdvice">
<!--配置目标类的方法执行时,使用通知类的before方法进行前置、后置增强-->
<aop:before method="before" pointcut-ref="myPointcut"/>
<aop:after method="before" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config>
3.xml配置介绍
切点表达式
execution([修饰符] 返回值类型 包名.类名.方法名([参数]))
表示要拦截那个方法(全限定方法名)
访问修饰符可以省略
返回值类型、包名、类名、方法名可以使用星号 * 代替,代表任意
包名与类名之间一个点 . 代表当前包下的类,两个点 .. 表示当前包及其子包下的类
参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表
通知类型
<aop:通知类型 method=“通知类中方法名” pointcut=“切点表达式"></aop:通知类型>
或
<aop:通知类型 method=“通知类中方法名” pointcut-ref=“切点名"></aop:通知类型>
4.用注解代替xml文件
在目标类和通知类加入注解将他们交给spring
并为通知类配置切面
在spring配置文件中加入包扫描和自动代理
<context:component-scan base-package="com.esthome"/>
<aop:aspectj-autoproxy/>
5.注解详解
切点表达式的抽取
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(* com.easthome..*.*(..))")
public void myPoint(){}
@Before("MyAdvice.myPoint()")
public void before() {
System.out.println("前置通知...");
}
通知类型
总结
- 使用@Aspect注解,标注切面类
- 使用@Before等注解,标注通知方法
- 使用@Pointcut注解,抽取切点表达式
- 配置aop自动代理 aop:aspectj-autoproxy
spring的事务
1.spring中事务的控制方式
- Spring的事务控制可以分为编程式事务控制和声明式事务控制。
- 编程式
- 开发者直接把事务的代码和业务代码耦合到一起,在实际开发中不用。
- 声明式
- 开发者采用配置的方式来实现的事务控制,业务代码与事务代码实现解耦合,使用的AOP思想。
2.事务管理器
事务有四种状态 :开启、提交、回滚、关闭;
PlatformTransactionManager接口,是事务管理器提供了以下方法可操作事务
PlatformTransactionManager 是接口类型,不同的 Dao 层技术则有不同的实现类。
- Dao层技术是jdbcTemplate或mybatis时:
- DataSourceTransactionManager
- Dao层技术是hibernate时:
- HibernateTransactionManager
- Dao层技术是JPA时:
- JpaTransactionManager
3.事务的信息
- TransactionDefinition接口提供事务的定义信息(事务隔离级别、事务传播行为等等)提供的方法
事务的隔离级别
- 设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读(幻读)。
* ISOLATION_DEFAULT 使用数据库默认级别
* ISOLATION_READ_UNCOMMITTED 读未提交
* ISOLATION_READ_COMMITTED 读已提交
* ISOLATION_REPEATABLE_READ 可重复读
* ISOLATION_SERIALIZABLE 串行化
事务传播行为
- 事务传播行为指的就是当一个业务方法【被】另一个业务方法调用时,应该如何进行事务控制
- read-only(是否只读):建议查询时设置为只读
- timeout(超时时间):默认值是-1,没有超时限制。如果有,以秒为单位进行设置
4.事务的状态
- TransactionStatus 接口提供的是事务具体的运行状态
- 可以简单的理解三者的关系:事务管理器通过读取事务定义参数进行事务管理,然后会产生一系列的事务状态。
5.总结
- Spring中的事务控制主要就是通过这三个API实现的
- PlatformTransactionManager 负责事务的管理,它是个接口,其子类负责具体工作
6.基于XML的声明式事务控制
引入事务依赖
<!--spring 事务管理-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.20</version>
</dependency>
在spring.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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
事务管理器通知配置
<!--事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--事务管理 配置通知类advice-->
<tx:advice id="myadvice" transaction-manager="transactionManager">
<!--事物的属性-->
<tx:attributes>
<!--匹配所有的方法-->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
配置切面
<!--aop设置切点-->
<aop:config>
<aop:advisor advice-ref="myadvice" pointcut="execution(public void com.esthome.service.AccountServiceImp.transfer(..))"/>
</aop:config>
<!--增删改查常用配置-->
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
7.基于注解的声明式事务控制
在xml配置文件中加入此配置
<!--事务管理器-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事务的注解支持-->
<tx:annotation-driven/>
在service层的目标类的目标方法加入此注解
@Transactional
标签:事务,spring,通知,aop,springAOP,注解,切面
From: https://blog.csdn.net/qq_65993561/article/details/142422906