spring的AOP配置之XML方式
AOP概念
? AOP(Aspect Oriented Programing)面向切面編程,一種編程范式,隸屬于軟工范疇,指導開發者如
何組織程序結構
? AOP彌補了OOP的不足,基于OOP基礎之上進行橫向開發
◆ OOP規定程序開發以類為主體模型,一切圍繞對象進行,完成某個任務先構建模型
◆ AOP程序開發主要關注基于OOP開發中的共性功能,一切圍繞共性功能進行,完成某個任務先
構建可能遇到的所有共性功能(當所有功能都開發出來也就沒有共性與非共性之分)
AOP動態代理的方式(spring的AOP默認是JDK Proxy)
<!-- 配置AOPproxy-target-class="false"配置為false就是使用的JDK Proxy由源碼得:<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false"><xsd:annotation><xsd:documentation><![CDATA[是否要創建基于類(CGLIB)的代理?默認情況下,標準創建基于Java接口的代理。Are class-based (CGLIB) proxies to be created? By default, standardJava interface-based proxies are created.]]></xsd:documentation></xsd:annotation></xsd:attribute> --><aop:config proxy-target-class="false"></aop:config>JDK的動態代理,需要有實現接口
動態代理——JDK Proxy
? JDKProxy動態代理是針對對象做代理,要求原始對象具有接口實現,并對接口方法進行增強
在aop動態代理的時候發現這個類是實現接口的類,就選擇JDK的動態代理,從ioc中獲取這個動態代理的實現類就需要按照接口.class去獲取
CGLIB動態代理方式,繼承方式
動態代理——CGLIB
? CGLIB(Code Generation Library),Code生成類庫
? CGLIB動態代理不限定是否具有接口,可以對任意操作進行增強
? CGLIB動態代理無需要原始被代理對象,動態創建出新的代理對象
需要將配置文件中這個設置為true才開啟CGLIB方式動態代理
CGLIB動態代理方式,繼承方式,就直接用這個類.class去獲取
AOP作用
? 伴隨著AOP時代的降臨,可以從各個行業的標準化、規范化開始入手,一步一步將所有共性功能逐一開
發完畢,最終以功能組合來完成個別業務模塊乃至整體業務系統的開發
? 目標:將軟件開發由手工制作走向半自動化/全自動化階段,實現“插拔式組件體系結構”搭建
AOP概念圖解
AOP
? Joinpoint(連接點):就是方法
? Pointcut(切入點):就是挖掉共性功能的方法
? Advice(通知):就是共性功能,最終以一個方法的形式呈現
? Aspect(切面):就是共性功能與挖的位置的對應關系
? Target(目標對象):就是挖掉功能的方法對應的類產生的對象,這種對象是無法直接完成最終工作的
? Weaving(織入):就是將挖掉的功能回填的動態過程
? Proxy(代理):目標對象無法直接完成工作,需要對其進行功能回填,通過創建原始對象的代理對象實現
? Introduction(引入/引介) :就是對原始對象無中生有的添加成員變量或成員方法
AOP配置之XML方式
AOP開發過程
? 開發階段(開發者完成)
◆ 正常的制作程序
◆ 將非共性功能開發到對應的目標對象類中,并制作成切入點方法
◆ 將共性功能獨立開發出來,制作成通知
◆ 在配置文件中,聲明切入點
◆ 在配置文件中,聲明切入點與通知間的關系(含通知類型),即切面
? 運行階段(AOP完成)
◆ Spring容器加載配置文件,監控所有配置的切入點方法的執行
◆ 當監控到切入點方法被運行,使用代理機制,動態創建目標對象的代理對象,根據通知類別,在代理對象的對應
位置將通知對應的功能織入,完成完整的代碼邏輯并運行
XML標簽
切入點表達式
通知類型
? AOP的通知類型共5種
◆ 前置通知:原始方法執行前執行,如果通知中拋出異常,阻止原始方法運行
應用:數據校驗
◆ 后置通知:原始方法執行后執行,無論原始方法中是否出現異常,都將執行通知
應用:現場清理
◆ 返回后通知:原始方法正常執行完畢并返回結果后執行,如果原始方法中拋出異常,無法執行
應用:返回值相關數據處理
◆ 拋出異常后通知:原始方法拋出異常后執行,如果原始方法沒有拋出異常,無法執行
應用:對原始方法中出現的異常信息進行處理
◆ 環繞通知:在原始方法執行前后均有對應執行執行,還可以阻止原始方法的執行
應用:十分強大,可以做任何事情
通知類型XML
一 在pom文件中導入相關坐標
AspectJ
? Aspect(切面)用于描述切入點與通知間的關系,是AOP編程中的一個概念
? AspectJ是基于java語言對Aspect的實現
二 將需要對切入點(方法)進行添加的功能制作成一個切面類,并存放在ioc容器中
切面類
package com.fs.aop;import org.aspectj.lang.ProceedingJoinPoint;/* 這個類是AOP的切面類里面編輯一些織入的方法*/ public class AOPDemoAdvice {public void proxyAOPBefore(){System.out.println("給切入點(方法)添加了前置通知~~~");}public void proxyAOPAfter(){/*這個后置通知是無論代碼是否出現異常,都會執行這個通知*/System.out.println("給切入點(方法)添加了后置通知~~~");}public void proxyAOPBeforeReturning() {/*BeforeReturning表示的是代碼運行成功無任何異常,會執行的通知*/System.out.println("給切入點(方法)添加了代碼運行成功后的后置通知~~~");}public void proxyAOPBeforeThrowing() {System.out.println("給切入點(方法)添加了代碼運行異常后的后置通知~~~");}/*環繞通知環繞通知可以將上面的通知方法全部實現ProceedingJoinPoint這類就代表切入點,可以給這個切入點執行配置通知*/public Object proxyAOPAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {Object proceed = null;try {//proceedingJoinPoint切入點執行前配置前置通知System.out.println("環繞通知的前置通知執行的代碼");//切入點(被動態代理的方法)執行proceed = proceedingJoinPoint.proceed();//proceedingJoinPoint切入點執行成功無報錯后配置前置通知System.out.println("環繞通知的-成功運行-后執行的代碼");} catch (Throwable throwable) {//proceedingJoinPoint切入點執行前配置異常通知System.out.println("環繞通知的切入點執行-異常后-執行的代碼");throwable.printStackTrace();} finally {//proceedingJoinPoint切入點執行前后通知,就是代碼無論是異常,還成功運行,都會執行的增強代碼System.out.println("環繞通知的后置通知執行的代碼");}return proceed;} }目標對象(這里模擬三層架構的service,對service中的某些方法進行aop)
AopService接口
package com.fs.service;public interface AopService {void findAll();void add();void findById();void del();void update(); }AopServiceImpl實現類
package com.fs.service.impl;import com.fs.service.AopService;public class AopServiceImpl implements AopService {@Overridepublic void findAll() {System.out.println("業務層執行了findAll~~~");}@Overridepublic void add() {System.out.println("業務層執行了add~~~");}@Overridepublic void findById() {System.out.println("業務層執行了findById~~~");//制造異常來是異常通知生效 // int i = 1/0;}@Overridepublic void del() {System.out.println("業務層執行了del~~~");}@Overridepublic void update() {System.out.println("業務層執行了update~~~");} }編寫applicationContext.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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 將業務層實現類存放在ioc容器中,因為需要對某個類中的方法進行aop需要這個類也在ioc容器中--><bean id="aopService" class="com.fs.service.impl.AopServiceImpl"/> <!-- 將切面類也交給ioc管理--><bean id="aopDemoAdvice" class="com.fs.aop.AOPDemoAdvice"/><aop:config> <!-- 配置切入點(方法),那些方法需要增強execution(* com.fs.service.impl.*.find*(..))任意修飾符,任意返回值 com.fs.service.impl包下的任意類的find開頭的方法(任意參數)--><aop:pointcut id="pt" expression="execution(* com.fs.service.impl.*.find*(..))"/> <!-- 配置切面類(切入點與通知的關系指定),里面有增強的代碼(共性代碼)--><aop:aspect ref="aopDemoAdvice"> <!-- 給切入點(方法)執行的時候配置通知通俗點講就是給上面配置的切入點(方法)動態的對方法進行增強,并且創建一個動態代理對象存放在ioc的容器中--><!-- 配置前置通知--> <!-- <aop:before method="proxyAOPBefore" pointcut-ref="pt"/>--> <!-- 配置后置通知--> <!-- <aop:before method="proxyAOPAfter" pointcut-ref="pt"/>--> <!-- 配置運行成功通知--> <!-- <aop:after-returning method="proxyAOPBeforeReturning" pointcut-ref="pt"/>--> <!-- 配置運行異常通知--> <!-- <aop:after-throwing method="proxyAOPBeforeThrowing" pointcut-ref="pt"/>--><!-- 配置環繞通知(可以實現上面的任意通知方式)--><aop:around method="proxyAOPAround" pointcut-ref="pt"/></aop:aspect></aop:config> </beans>測試代碼
@Testpublic void method02() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationAop.xml");/*JDK的動態代理,需要有實現接口在aop動態代理的時候發現這個類是實現接口的類,就選擇JDK的動態代理若aop動態代的時候發現這個類是普通類,就選擇CGLIB動態代理方式,繼承方式,就不會因為當前業務實現類被aop動態代理增強方法后生成了一個類,這個類的不是AopServiceImpl所以在ioc中獲取使用AopServiceImpl.class是拿不到的,只能通過AopService接口去ioc中找因為aop動態代理生成的實現類還是實現了AopService,所以可以通過接口類型去ioc中找到這個aop動態代理的實現類*/ // AopServiceImpl aopService = applicationContext.getBean(AopServiceImpl.class);AopService aopService = applicationContext.getBean(AopService.class); // aopService.findAll();aopService.findById();}測試效果
findById()方法正常運行
若在findById()方法中制作一個異常
@Overridepublic void findById() {System.out.println("業務層執行了findById~~~");//制造異常來是異常通知生效int i = 1/0;}圖解Aop
通知獲取參數數據(了解)
若有多個參數,JoinPoint一定要在第一個參數的位子
通知獲取返回值數據
通知獲取異常數據
總結
以上是生活随笔為你收集整理的spring的AOP配置之XML方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring整合Mybatis之注解方式
- 下一篇: spring的AOP配置之@注解方式