AOP
概述:AspectOrientedProgramming 面向切面編程:是對面向對象編程的補充延續,面向切面編程思想是將程序中非業務代碼(提交事務,打印日志,權限驗證,統一異常處理)
然后在調用業務代碼時,通過一個代理對象幫助我們調用這些提取出來的非業務代碼,這樣在業務代碼不用顯示的調用非業務代碼,做到的業務代碼和非業務代碼的分離,降低了耦合度。
????????好處:模塊之間的耦合度降低了
????????原理:動態代理模式 給業務代碼生成代理對象
AOP的基本概念
? ? 連接點(Joinpoint):類中可以被增強(加功能)的方法,這個方法就被稱為連接點
? ? 切入點(pointcut):類中有很多方法可以被增強,但實際中只有add和update 被增了,那么add和update方法就被稱為切入點(實際實現的連接點)
? ? 通知(Advice): 通知是指一個切面在特定的連接點要做的事情(增強的功能)。通知分為方法執行前通知,方法執行后通知,環繞通知等.
? ? 目標(Target): 代理的目標對象(連接點,切入點所在類)
? ? 代理(Proxy): 向目標對象應用通知時創建的代理對象
springAOP 實現
? ? ? ? 在pom.xml文件中導入AOP相關的jar包(AspectJ)
<!--spring aop--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.2.2.RELEASE</version></dependency>
? ?? ? ?在spring.xml文件中配置開啟AspectJ的自動代理
<!--開啟自動代理--><aop:aspectj-autoproxy />
AspectJ中常用的通知有五種類型:
????????通知,向連接點添加的功能
注解實例:
? 1.@before()
????????@Before() 前置通知 在業務方法執行之前調用執行
/*execution:表達式的主體第一處*:返回的類型(這里代表所有類型)com.ffyc.springpro.dao:攔截的包名第二處*:類名第三處*:方法名(..):表示方法的參數,".."表示任意參數
*/@Before("execution(* com.ffyc.springpro.dao.*.*(..))")
public void printlog(){System.out.println("打印日志");}
????????????????????????
2.@After()
????????@After() 后置通知 在業務方法執行完后調用執行 即使業務代碼中出現了異常,也會執行
@After("execution(* com.ffyc.springpro.dao.*.*(..))")
public void printlog(){System.out.println("打印日志");}
????????????????? ? ? ?
3.@AfterReturning()
?????????@AfterReturning() 返回通知 在業務方法執行完后再執行 當業務代碼中出現了異常,不會執行
public void insert(){System.out.println("新增");System.out.println(10/0);}
@AfterReturning("execution(* com.ffyc.springpro.dao.*.*(..))")public void printlog(){System.out.println("打印日志");}
4.@AfterThrowing()
?????????@AfterThrowing() 異常通知 當業務代碼出現異常時,調用執行
public void insert(){System.out.println("新增");System.out.println(10/0);}
@AfterThrowing(value = "execution(* com.ffyc.springpro.dao.*.*(..))",throwing = "e")public void exception(Throwable e){System.out.println("系統忙"+e.getMessage());e.printStackTrace();}
前四個注解為一組,一并使用。
5.@Around()
????????@Around 環繞通知 可以在業務方法執行之前,之后,出異常時添加功能
@Around(value = "execution(* com.ffyc.springpro.dao.*.*(..))")public void around(ProceedingJoinPoint joinPoint){//ProceedingJoinPoint joinPoint 表示的是目標方法System.out.println("前置通知");try {Object[] obj = joinPoint.getArgs();//獲取目標方法的參數System.out.println(Arrays.toString(obj));Object object = joinPoint.proceed();//調用目標業務方法System.out.println("返回通知");} catch (Throwable throwable) {throwable.printStackTrace();System.out.println("異常通知");}System.out.println("后置通知");}
????????
第五種@around注解相當于將前四個注解做的一個集合。
Spring 事物管理
? ? 事務管理本質上是數據庫提供的一種管理機制。
????????數據庫事務管理是對一次數據庫操作過程中執行的多條語句進行管理。
????????確保一次操作過程中的多條sql語句要么都執行成功,要么都不執行,從而保證數據一致性。
????????????????例如:轉賬: sql1 A-500 sql2 B+500 確保轉賬數據的一致
? ? spring事務管理是spring框架對事務提交這一功能進行封裝,程序員在業務開發中不需要顯示的提交事務。
Spring中的事務管理分為兩種方式:
1、編程式事務管理
????????需要程序員在代碼中自己控制事務提交和回滾
2、聲明式事務管理
????????聲明事務底層使用了AOP思想,可以為方法添加事務功能,它的控制是方法級別的
????????基于注解實現的spring事務管理 Spring 框架,提供事物管理實現類是DataSourceTransactionManager.
????????在spring.xml文件中配置以下兩個步驟
? ? ? ?1.配置事物管理器
<!-- 配置spring 事務管理器--><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="druidDataSource"></property></bean>
? ? ? ? 2.開啟注解事務管理
<!-- 開啟注解事務管理--><tx:annotation-driven transaction-manager="transactionManager"/>
? ? ? ??在類或方法上使用@Transactional標簽即可.
????????@Transactional 可以添加在方法上,也可以添加到類上面
???????????????????????????????? 如果添加在類上面,此類中的所有方法都在spring事務管理中運行
????????聲明式事務失效的情況
???????? 1.@Transactional 用在非public修飾的方法上
???????? 2.方法中的異常被捕獲了,認為方法沒有異常
???????? 3.方法中出現編譯期異常,還是會提交事務 解決方案:@Transactional(rollbackFor = Exception.class)
???????? 4.數據庫引擎不支持事務 mysql中只有innodb引擎支持事務的