文章目錄
- 1.SpringAOP
- 1.1 什么是 AOP
- 1.2 AOP 的作用及其優勢
- 1.3 AOP 的底層實作
- 1.4 AOP 的動態代理技術
- 1.5 JDK 的動態代理
- 1.6 cglib 的動態代理
- 1.7 AOP 相關概念
- 1.8 AOP 開發明確的事項
- 1.9 知識要點
- 2. 基于 XML 的 AOP 開發
- 2.1 快速入門
- 2.2 XML 配置 AOP 詳解
- 1) 切點運算式的寫法
- 2) 通知的型別
- 3) 切點運算式的抽取
- 2.3 知識要點
- 3.基于注解的 AOP 開發
- 3.1 快速入門
- 3.2 注解配置 AOP 詳解
- 1) 注解通知的型別
- 2) 切點運算式的抽取
1.SpringAOP
1.1 什么是 AOP
AOP 為 Aspect Oriented Programming 的縮寫,意思為面向切面編程,是通過預編譯方式和運行期動態代理實作程式功能的統一維護的一種技術,
AOP 是 OOP 的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函式式編程的一種衍生范型,利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率,
1.2 AOP 的作用及其優勢
作用:在程式運行期間,在不修改原始碼的情況下對方法進行功能增強
優勢:減少重復代碼,提高開發效率,并且便于維護
1.3 AOP 的底層實作
實際上,AOP 的底層是通過 Spring 提供的的動態代理技術實作的,在運行期間,Spring通過動態代理技術動態的生成代理物件,代理物件方法執行時進行增強功能的介入,在去呼叫目標物件的方法,從而完成功能的增強,
1.4 AOP 的動態代理技術
常用的動態代理技術
- JDK 代理 : 基于介面的動態代理技術
- cglib 代理:基于父類的動態代理技術

1.5 JDK 的動態代理
①目標類介面
public interface TargetInterface {
public void method();
}
②目標類
public class Target implements TargetInterface {
@Override
public void method() {
System.out.println("Target running....");
}
}
③動態代理代碼
Target target = new Target(); //創建目標物件
//創建代理物件
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass()
.getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("前置增強代碼...");
Object invoke = method.invoke(target, args);
System.out.println("后置增強代碼...");
return invoke;
}
}
);
④ 呼叫代理物件的方法測驗
// 測驗,當呼叫介面的任何方法時,代理物件的代碼都無需修改
proxy.method();

1.6 cglib 的動態代理
①目標類
public class Target {
public void method() {
System.out.println("Target running....");
}
}
②動態代理代碼
Target target = new Target(); //創建目標物件
Enhancer enhancer = new Enhancer(); //創建增強器
enhancer.setSuperclass(Target.class); //設定父類
enhancer.setCallback(new MethodInterceptor() { //設定回呼
@Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
System.out.println("前置代碼增強....");
Object invoke = method.invoke(target, objects);
System.out.println("后置代碼增強....");
return invoke;
}
});
Target proxy = (Target) enhancer.create(); //創建代理物件
③呼叫代理物件的方法測驗
//測驗,當呼叫介面的任何方法時,代理物件的代碼都無序修改
proxy.method();

1.7 AOP 相關概念
Spring 的 AOP 實作底層就是對上面的動態代理的代碼進行了封裝,封裝后我們只需要對需要關注的部分進行代碼撰寫,并通過配置的方式完成指定目標的方法增強,
在正式講解 AOP 的操作之前,我們必須理解 AOP 的相關術語,常用的術語如下:
-
Target(目標物件):代理的目標物件
-
Proxy (代理):一個類被 AOP 織入增強后,就產生一個結果代理類
-
Joinpoint(連接點):所謂連接點是指那些被攔截到的點,在spring中,這些點指的是方法,因為spring只支持方法型別的連接點
-
Pointcut(切入點):所謂切入點是指我們要對哪些 Joinpoint 進行攔截的定義
-
Advice(通知/ 增強):所謂通知是指攔截到 Joinpoint 之后所要做的事情就是通知
-
Aspect(切面):是切入點和通知(引介)的結合
-
Weaving(織入):是指把增強應用到目標物件來創建新的代理物件的程序,spring采用動態代理織入,而AspectJ采用編譯期織入和類裝載期織入
1.8 AOP 開發明確的事項
1)需要撰寫的內容
-
撰寫核心業務代碼(目標類的目標方法)
-
撰寫切面類,切面類中有通知(增強功能方法)
-
在組態檔中,配置織入關系,即將哪些通知與哪些連接點進行結合
2)AOP 技術實作的內容
Spring 框架監控切入點方法的執行,一旦監控到切入點方法被運行,使用代理機制,動態創建目標物件的代理物件,根據通知類別,在代理物件的對應位置,將通知對應的功能織入,完成完整的代碼邏輯運行,
3)AOP 底層使用哪種代理方式
在 spring 中,框架會根據目標類是否實作了介面來決定采用哪種動態代理的方式,
1.9 知識要點
-
aop:面向切面編程
-
aop底層實作:基于JDK的動態代理 和 基于Cglib的動態代理
-
aop的重點概念:
Pointcut(切入點):被增強的方法 Advice(通知/ 增強):封裝增強業務邏輯的方法 Aspect(切面):切點+通知 Weaving(織入):將切點與通知結合的程序 -
開發明確事項:
誰是切點(切點運算式配置) 誰是通知(切面類中的增強方法) 將切點和通知進行織入配置
2. 基于 XML 的 AOP 開發
2.1 快速入門
①匯入 AOP 相關坐標
②創建目標介面和目標類(內部有切點)
③創建切面類(內部有增強方法)
④將目標類和切面類的物件創建權交給 spring
⑤在 applicationContext.xml 中配置織入關系
⑥測驗代碼
①匯入 AOP 相關坐標
②創建目標介面和目標類(內部有切點)
public interface TargetInterface {
public void method();
}
public class Target implements TargetInterface {
@Override
public void method() {
System.out.println("Target running....");
}
}
③創建切面類(內部有增強方法)
public class MyAspect {
//前置增強方法
public void before(){
System.out.println("前置代碼增強.....");
}
}
④將目標類和切面類的物件創建權交給 spring
<!--配置目標類-->
<bean id="target" class="com.itheima.aop.Target"></bean>
<!--配置切面類-->
<bean id="myAspect" class="com.itheima.aop.MyAspect"></bean>
⑤在 applicationContext.xml 中配置織入關系
- 匯入aop命名空間
- 配置切點運算式和前置增強的織入關系
<aop:config>
<!--參考myAspect的Bean為切面物件-->
<aop:aspect ref="myAspect">
<!--配置Target的method方法執行時要進行myAspect的before方法前置增強-->
<aop:before method="before" pointcut="execution(public void com.itheima.aop.Target.method())"></aop:before>
</aop:aspect>
</aop:config>
⑥測驗代碼
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Autowired
private TargetInterface target;
@Test
public void test1(){
target.method();
}
}
⑦測驗結果

2.2 XML 配置 AOP 詳解
1) 切點運算式的寫法
運算式語法:
execution([修飾符] 回傳值型別 包名.類名.方法名(引數))
-
訪問修飾符可以省略
-
回傳值型別、包名、類名、方法名可以使用星號* 代表任意
-
包名與類名之間一個點 . 代表當前包下的類,兩個點 … 表示當前包及其子包下的類
-
引數串列可以使用兩個點 … 表示任意個數,任意型別的引數串列
例如:
execution(public void com.itheima.aop.Target.method())
execution(void com.itheima.aop.Target.*(..))
execution(* com.itheima.aop.*.*(..))
execution(* com.itheima.aop..*.*(..))
execution(* *..*.*(..))
2) 通知的型別
通知的配置語法:
<aop:通知型別 method=“切面類中方法名” pointcut=“切點運算式"></aop:通知型別>

3) 切點運算式的抽取
當多個增強的切點運算式相同時,可以將切點運算式進行抽取,在增強中使用 pointcut-ref 屬性代替 pointcut 屬性來參考抽取后的切點運算式,
<aop:config>
<!--參考myAspect的Bean為切面物件-->
<aop:aspect ref="myAspect">
<aop:pointcut id="myPointcut" expression="execution(* com.itheima.aop.*.*(..))"/>
<aop:before method="before" pointcut-ref="myPointcut"></aop:before>
</aop:aspect>
</aop:config>
2.3 知識要點
- aop織入的配置
<aop:config>
<aop:aspect ref=“切面類”>
<aop:before method=“通知方法名稱” pointcut=“切點運算式"></aop:before>
</aop:aspect>
</aop:config>
- 通知的型別:前置通知、后置通知、環繞通知、例外拋出通知、最終通知
- 切點運算式的寫法:
execution([修飾符] 回傳值型別 包名.類名.方法名(引數))
3.基于注解的 AOP 開發
3.1 快速入門
基于注解的aop開發步驟:
①創建目標介面和目標類(內部有切點)
②創建切面類(內部有增強方法)
③將目標類和切面類的物件創建權交給 spring
④在切面類中使用注解配置織入關系
⑤在組態檔中開啟組件掃描和 AOP 的自動代理
⑥測驗
①創建目標介面和目標類(內部有切點)
public interface TargetInterface {
public void method();
}
public class Target implements TargetInterface {
@Override
public void method() {
System.out.println("Target running....");
}
}
②創建切面類(內部有增強方法)
public class MyAspect {
//前置增強方法
public void before(){
System.out.println("前置代碼增強.....");
}
}
③將目標類和切面類的物件創建權交給 spring
@Component("target")
public class Target implements TargetInterface {
@Override
public void method() {
System.out.println("Target running....");
}
}
@Component("myAspect")
public class MyAspect {
public void before(){
System.out.println("前置代碼增強.....");
}
}
④在切面類中使用注解配置織入關系
@Component("myAspect")
@Aspect
public class MyAspect {
@Before("execution(* com.itheima.aop.*.*(..))")
public void before(){
System.out.println("前置代碼增強.....");
}
}
⑤在組態檔中開啟組件掃描和 AOP 的自動代理
<!--組件掃描-->
<context:component-scan base-package="com.itheima.aop"/>
<!--aop的自動代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
⑥測驗代碼
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Autowired
private TargetInterface target;
@Test
public void test1(){
target.method();
}
}
3.2 注解配置 AOP 詳解
1) 注解通知的型別
通知的配置語法:@通知注解(“切點運算式")

2) 切點運算式的抽取
同 xml配置aop 一樣,我們可以將切點運算式抽取,抽取方式是在切面內定義方法,在該方法上使用@Pointcut注解定義切點運算式,然后在在增強注解中進行參考,具體如下:
@@Component("myAspect")
@Aspect
public class MyAspect {
@Before("MyAspect.myPoint()")
public void before(){
System.out.println("前置代碼增強.....");
}
@Pointcut("execution(* com.itheima.aop.*.*(..))")
public void myPoint(){}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/258930.html
標籤:java
上一篇:Arraylist擴容機制理解
