AI智能
改变未来

Spring AOP及事务配置三种模式详解


Spring AOP简述

Spring AOP的设计思想,就是通过动态代理,在运行期对需要使用的业务逻辑方法进行增强。

使用场景如:日志打印、权限、事务控制等。

默认情况下,Spring会根据被代理的对象是否实现接口来选择使用JDK还是CGLIB。当被代理对象没有实现接口时,Spring会选择CGLIB。当实现了接口,Spring会选择JDK官方的代理技术,不过我们也可以通过配置的方式,让Spring强制使用CGLIB。

配置方式有两种:

  • 使⽤aop:config标签配置
<aop:config proxy-target-class="true">
  • 使⽤aop:aspectj-autoproxy标签配置
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

Spring中AOP的实现

2.1 XML模式

  1. 引入依赖(如果项目里没有的话)
<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.1.12.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency>
  1. xml配置

主要看下面的aop部分

<?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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttps://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd">

xml相关切面配置

<bean id="logUtil" class="com.mmc.ioc.utils.LogUtil"></bean><!--aop的配置--><!--aop的配置--><aop:config><!--配置切面--><aop:aspect id="logAdvice" ref="logUtil"><aop:pointcut id="logAspect" expression="execution(public * com.mmc.ioc.service.impl.TransferServiceImpl.transfer(..))"></aop:pointcut><!--前置通知--><aop:before method="printLog" pointcut-ref="logAspect"></aop:before><!--后置通知,无论业务是否正常执行--><aop:after method="after" pointcut-ref="logAspect"></aop:after><!--正常执行--><aop:after-returning method="afterReturn" pointcut-ref="logAspect"></aop:after-returning><!--异常执行--><aop:after-throwing method="afterException" pointcut-ref="logAspect"></aop:after-throwing><!--环绕通知--><!--<aop:around method="around" pointcut-ref="logAspect" arg-names="proceedingJoinPoint"></aop:around>--></aop:aspect></aop:config>

环绕通知可以实现上面的4种通知,并且可以控制业务方法是否执行。通过如下代码控制:

proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
public class LogUtil {public void printLog(){System.out.println("打印日志");}public void after(){System.out.println("后日志打印,不管业务是否正常");}public void afterReturn(){System.out.println("正常执行完毕打印日志");}public void afterException(){System.out.println("异常执行打印日志");}public void around(ProceedingJoinPoint proceedingJoinPoint){System.out.println("环绕前置");try {Object result =proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());System.out.println("环绕正常执行");} catch (Throwable throwable) {throwable.printStackTrace();System.out.println("环绕异常执行");}}}
  1. 切入点表达式

举例:

public voidcom.lagou.service.impl.TransferServiceImpl.updateAccountByCardNo(com.lagou.pojo.Account)
  • 访问修饰符可以省略,也就是public可以不用写
void com.mmc.ioc.service.impl.TransferServiceImpl.transfer(String,String,int)
  • 返回值可以用*代替,表示返回任意值
* com.mmc.ioc.service.impl.TransferServiceImpl.transfer(String,String,int)
  • 包名可以使用..表示当前包及其子包
* com..TransferServiceImpl.transfer(String,String,int)
  • 类名和方法名,都可以使用*表示任意类,任意方法
* com..*(String,String,int))
  • 参数列表,如果是基本类型可以直接写名称,如int。引用类型必须用全限定名称
  • 参数列表可以使用*代替任意参数类型,但必须有参数
* com..*(*)
  • 参数列表可以使用..代替任意参数类型,有无参数均可
* com..*(*)
  • 全通配方式:
* *..*.*(..)

2.2 XML+注解模式

  1. XML中开启Spring对注解AOP的支持
<!--开启spring对注解aop的⽀持--><aop:aspectj-autoproxy/>
  1. 注解配置
@Component@Aspectpublic class LogUtil {@Pointcut("execution(* com.mmc.ioc.service.impl.TransferServiceImpl.transfer(..))")public void pointcut(){}@Before("pointcut()")public void printLog(){System.out.println("打印日志");}@After("pointcut()")public void after(){System.out.println("后日志打印,不管业务是否正常");}@AfterReturning("pointcut()")public void afterReturn(){System.out.println("正常执行完毕打印日志");}@AfterThrowing("pointcut()")public void afterException(){System.out.println("异常执行打印日志");}//    @Around("pointcut()")public void around(ProceedingJoinPoint proceedingJoinPoint){System.out.println("环绕前置");try {Object result =proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());System.out.println("环绕正常执行");} catch (Throwable throwable) {throwable.printStackTrace();System.out.println("环绕异常执行");}}}

2.3 纯注解模式

只需要用注解@EnableAspectJAutoProxy替换掉

<aop:aspectj-autoproxy/>

Spring事务配置

也分为3种模式

3.1 XML模式

  1. 引入pom依赖
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.12.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.1.12.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.1.12.RELEASE</version></dependency>
  1. xml配置
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><constructor-arg name="dataSource" ref="dataSource"></constructor-arg></bean><tx:advice id="txAdice" transaction-manager="transactionManager"><!--定制事务细节--><tx:attributes><tx:method name="*" read-only="false" propagation="REQUIRED" isolation="DEFAULT"/><tx:method name="query*" read-only="true" propagation="SUPPORTS"></tx:method></tx:attributes></tx:advice><!--事务衡器逻辑--><aop:config><aop:advisor advice-ref="txAdice" pointcut="execution(* com.mmc.ioc.service.impl.TransferServiceImpl.transfer(..))"></aop:advisor></aop:config>

3.2 基于XML+注解

  1. xml配置:
<!--spring声明式事务配置--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><constructor-arg name="dataSource" ref="dataSource"></constructor-arg></bean><tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
  1. 在类或方法上面添加@Transactional注解
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)

3.3 纯注解

用@EnableTransactionManagement 注解替换掉

<tx:annotation-driven transaction-manager="transactionManager"/>

即可

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » Spring AOP及事务配置三种模式详解