二、AOP
1、AOP术语
AOP面向切面编程,是对oop的补充。aop的底层就是动态代理,他的功能就是将动态代理进行友好的封装。
AOP相关术语:
Joinpoint( 连接点):类中的方法称为连接点
Pointcut( 切入点):连接点所在的类称为节入点
Advice( 通知/ 增强):以前动态代理类中编写的业务代码称为通知
Aspect( 切面):通知+切入点
Weaving( 织入):通知和连接点进行关联的过程
通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
2、AOP配置步骤
-
导入aop坐标
<!--spring aop坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.9.RELEASE</version>
</dependency> -
导入aop名称空间(xml配置才需要)
-
在xml中配置aop
配置前需要将通知类和切入点类进行实例化
<!--配置aop-->
<aop:config>
<!--配置切面 通知+切入点-->
<aop:aspect id="asp" ref="loggers">
<!--配置切入点
expression:切入点表达式,告诉切面要对哪些类下的哪些方法进行增强
-->
<aop:pointcut id="pot" expression="execution(* cn.woniu.service.impl.*.*(..))"/>
<!--配置通知的织入-->
<aop:before method="show" pointcut-ref="pot"></aop:before>
</aop:aspect>
</aop:config> -
aop说明
spring-aop和spring-aspects包的区别
spring-aop:是spring中提供aop功能的包,但是该包中没有提供解析切入点表达式的功能,还需要导入aspectsj坐标才能正确解析切入点表达式
spring-aspects:可以理解为是aop的框架,将aspectsj功能与aop功能进行封装
springaop默认使用的是jdk接口代理,在注入对象时需要使用对象的接口来接收,否则报错。可以强制改为使用cglib代理。需要导入cglib坐标
<aop:config proxy-target-class="true">
3、切入点表达式写法
语法:
execution(访问修饰符 包名.包名.包名.方法名(参数))
常用写法:
任意公共方法的执行:
execution(public * *(..))
任何一个名字以“set”开始的方法的执行
execution(* set*(..))
AccountService
接口定义的任意方法的执行:
execution(* com.xyz.service.AccountService.*(..))
在service包中定义的任意方法的执行:
execution(* com.xyz.service.*.*(..))
在service包或其子包中定义的任意方法的执行:<font color=red>【常用方式】</font>
execution(* com.xyz.service..*.*(..))
三、aop的通知
Spring中一共有5种通知:前置通知(before)、后置通知(returning)、异常通知(throwing)、最终通知(after)、环绕通知(around)
前置通知(before):在连接点方法执行前执行
后置通知(after-returning):在连接点方法执行之后执行
异常通知(after-throwing):在连接点方法出现异常时执行
<font color=red>注意:异常通知和后置通知只会出现一个。</font>.
最终通知(after):不管有没有发生异常,都会执行
环绕通知(around):可以将前四个通知都在环绕通知中调用,环绕通知执行的顺序是按哪个通知先调用就先执行谁。
1、xml配置通知
<!--配置aop-->
<aop:config proxy-target-class="false">
<!--配置切面 通知+切入点-->
<aop:aspect id="asp" ref="loggers">
<!--配置切入点
expression:切入点表达式,告诉切面要对哪些类下的哪些方法进行增强
-->
<aop:pointcut id="pot" expression="execution(* cn.woniu.service.impl.*.*(..))"/>
<!--配置通知的织入-->
<aop:before method="beforePrintLog" pointcut-ref="pot"></aop:before>
<!--后置通知-->
<aop:after-returning method="afterReturning" pointcut-ref="pot" ></aop:after-returning>
<!--异常通知-->
<aop:after-throwing method="afterThrowingLog" pointcut-ref="pot"></aop:after-throwing>
<!--最终通知-->
<aop:after method="afterLog" pointcut-ref="pot"></aop:after>
<!--配置环绕通知-->
<aop:around method="aroundPrintLog" pointcut-ref="pot"></aop:around>
</aop:aspect>
</aop:config>
2、注解配置通知
开启aop注解支持
<!--开启aop注解支持-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
通知类
四、aop实现事务控制
-
导入spring事务坐标
该jar包中提供了一组管理事务的api(开启事务,提交事务,回滚事务),这个类称为事务管理器
<!--spring事务-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.9.RELEASE</version>
</dependency>
1、xml方式配置实现事务控制
实例化事务管理器
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
编写通知(确定哪些方法使用什么事务[只读事务|可读写事务])
<!--配置事务的通知 区分同一个类中哪些方法使用只读事务,哪些方法使用可读写事务(提交,回滚)-->
<tx:advice id="txadv" transaction-manager="transactionManager">
<tx:attributes>
<!--配置哪些方法是只读事务-->
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
<!--配置增删改事务-->
<tx:method name="add*" propagation="REQUIRED"></tx:method>
<tx:method name="save*" propagation="REQUIRED"></tx:method>
<tx:method name="insert*" propagation="REQUIRED"></tx:method>
<tx:method name="update*" propagation="REQUIRED"></tx:method>
<tx:method name="delete*" propagation="REQUIRED"></tx:method>
<tx:method name="del*" propagation="REQUIRED"></tx:method>
</tx:attributes>
</tx:advice>
配置切面
<!--配置切面-->
<aop:config proxy-target-class="true">
<!--配置切入点表达式-->
<aop:pointcut id="pot" expression="execution(* cn.woniu.service.impl.*.*(..))"/>
<!--将通知织入到切入点中-->
<aop:advisor advice-ref="txadv" pointcut-ref="pot"></aop:advisor>
</aop:config>
2、注解实现事务配置
-
在spring配置类中开启事务注解支持
-
在spring配置类中配置事务管理器
/**
* 配置事务管理器
* @param dataSource
* @return
*/
-
在service类上添加事务注解