什麼是AOP?
AOP意爲:面向切面編程,利用AOP能夠對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度下降,提升程序的重要性,同時提升開發效率java
簡單說就是:它就是把咱們程序重複的代碼抽取出來,在須要執行的時候,使用動態代理的技術,在不修改源碼的基礎上,對咱們的已有方法進行加強。程序員
AOP的做用:
在程序運行期間,不修改源碼的狀況下對已有的方法加強spring
減小了代碼冗餘,提升代碼質量,維護方便express
AOP的實現技術:
使用動態代理的技術(自行補充此知識點)編程
AOP的相關術語
- Joinpoint(鏈接點): 所謂鏈接點是指那些被攔截到的點。在 spring 中,這些點指的是方法,由於 spring 只支持方法類型的 鏈接點。(加強的方法)
- Pointcut(切入點): 所謂切入點是指咱們要對哪些 Joinpoint 進行攔截的定義。 (所要加強的方法)
- Advice(通知/加強): 所謂通知是指攔截到 Joinpoint 以後所要作的事情就是通知。 通知的類型:前置通知,後置通知,異常通知,最終通知,環繞通知。
- Introduction(引介): 引介是一種特殊的通知在不修改類代碼的前提下, Introduction 能夠在運行期爲類動態地添加一些方 法或 Field。
- Target(目標對象): 代理的目標對象。
- Weaving(織入): 是指把加強應用到目標對象來建立新的代理對象的過程。 spring 採用動態代理織入,而 AspectJ 採用編譯期織入和類裝載期織入。
- Proxy(代理): 一個類被 AOP 織入加強後,就產生一個結果代理類。
- Aspect(切面): 是切入點和通知(引介)的結合。(通知類)
學習 spring 中的 AOP 要明確的事 :
a、開發階段(咱們作的) 編寫核心業務代碼(開發主線):大部分程序員來作,要求熟悉業務需求。 框架
把公用代碼抽取出來,製做成通知。(開發階段最後再作):AOP 編程人員來作。 在配置文件中,聲明切入點與通知間的關係,即切面。:AOP 編程人員來作。學習
b、運行階段(Spring框架完成的) Spring 框架監控切入點方法的執行。一旦監控到切入點方法被運行,使用代理機制,動態建立目標對 象的代理對象,根據通知類別,在代理對象的對應位置,將通知對應的功能織入,完成完整的代碼邏輯運行。 spa
環境搭建 :
導包:
附上包的網盤下載地址:代理
連接:https://pan.baidu.com/s/1hC13b1y4jUpoh89dhI2glg
提取碼:sz1a
xml
配置xml文件導入約束:
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
編寫servlet類 定義3個須要被加強的方法() ,及鏈接點
package AOP_servlet;
public class use_servlet implements interface_servlet {
public int select() {
System.out.println("查詢成功");
return 0;
}
public void delete() {
System.out.println("刪除成功");
}
public boolean insert(int i) {
System.out.println("插入成功");
return false;
}
}
編寫通知類(切面),定義加強方法(切入點)
package AOP_logger;
public class logger {
//前置通知
public void before() {
System.out.println("before") ;
}
//後置通知
public void after() {
System.out.println("after");
}
//異常通知
public void throwprint() {
System.out.println("throw");
}
//最終通知
public void last() {
System.out.println("last");
}
}
AOP標籤
-
使用 aop:config 聲明 aop 配置
做用:用於聲明開始 aop 的配置
<aop:config>
<!-- 配置的代碼都寫在此處 -->
</aop:config>
-
使用 aop:pointcut 配置切入點表達式
aop:pointcut: 做用: 用於配置切入點表達式。就是指定對哪些類的哪些方法進行加強。
屬性: expression:用於定義切入點表達式。 id:用於給切入點表達式提供一個惟一標識
<aop:pointcut expression="execution( public void com.itheima.service.impl.AccountServiceImpl.transfer( java.lang.String, java.lang.String, java.lang.Float) )" id="pt1"/>
public 方法權限能夠省略
方法類型能夠用 * 表示 任意返回類型
包能夠用 * 表示 *.. 表示當前包及其子包
類名能夠用 * 表示 全部方法
方法名用 * 表示 全部方法
方法參數用 (..) 表示任意參數
開發中 通常爲servlet中的類的全部方法加強 因此 "execution( * servtel.useservtel.*(..))"
-
使用 aop:aspect 配置切面
做用: 用於配置切面。
屬性: id:給切面提供一個惟一標識。 ref:引用配置好的通知類 bean 的 id。
<aop:aspect id="txAdvice" ref="txManager">
<!--配置通知的類型要寫在此處-->
</aop:aspect>
-
使用 aop:xxx 配置對應的通知類型
aop:before
做用: 用於配置前置通知。指定加強的方法在切入點方法以前執行
屬性:
method:用於指定通知類中的加強方法名稱
ponitcut-ref:用於指定切入點的表達式的引用
poinitcut:用於指定切入點表達式
執行時間點: 切入點方法執行以前執行
<aop:before method="beginTransaction" pointcut-ref="pt1"/>
aop:after-returning
做用: 用於配置後置通知
執行時間點: 切入點方法正常執行以後。
它和異常通知只能有一個執行 <aop:after-returning method="commit" pointcut-ref="pt1"/>
aop:after-throwing
做用: 用於配置異常通知
執行時間點: 切入點方法執行產生異常後執行。
它和後置通知只能執行一個 <aop:after-throwing method="rollback" pointcut-ref="pt1"/>
aop:after
做用: 用於配置最終通知
執行時間點: 不管切入點方法執行時是否有異常,它都會在其後面執行。
<aop:after method="release" pointcut-ref="pt1"/>
-
編寫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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置 Servlet類 IOC -->
<bean id="use_servlet" class="AOP_servlet.use_servlet"></bean>
<!-- 配置logger(通知)類 IOC -->
<bean id="logger" class="AOP_logger.logger"></bean>
<!-- 配置AOP -->
<aop:config proxy-target-class="true">
<!-- 配置切入點表達式 -->
<aop:pointcut expression="execution(* AOP_servlet.*.*(..))"
id="execution" />
<!-- 配置切面 -->
<aop:aspect id="aoplogger" ref="logger">
<!--配置切入點所要加強的方法 -->
<aop:before method="before" pointcut-ref="execution" />
<aop:after-returning method="after" pointcut-ref="execution" />
<aop:after-throwing method="throwprint"
pointcut-ref="execution" />
<aop:after method="last" pointcut-ref="execution" />
</aop:aspect>
</aop:config>
</beans>
-
環繞通知:
<!--配置切入點所要加強的方法 -->
<aop:around method="around" pointcut-ref="execution"/>
配置類:
package AOP_logger;
import org.aspectj.lang.ProceedingJoinPoint;
public class logger {
// 前置通知
public void before() {
System.out.println("before");
}
// 後置通知
public void after() {
System.out.println("after");
}
// 異常通知
public void throwprint() {
System.out.println("throw");
}
// 最終通知
public void last() {
System.out.println("last");
}
// 環繞通知
public void around(ProceedingJoinPoint pjp) {
try {
before();
// 切點方法執行
pjp.proceed();
after();
} catch (Throwable e) {
throwprint();
e.printStackTrace();
} finally {
last();
}
}
}
aop:pointcut: 做用: 用於配置切入點表達式。就是指定對哪些類的哪些方法進行加強。 屬性: expression:用於定義切入點表達式。 id:用於給切入點表達式提供一個惟一標識 <aop:pointcut expression="execution( public void com.itheima.service.impl.AccountServiceImpl.transfer( java.lang.String, java.lang.String, java.lang.Float) )" id="pt1"/> 2