網站首頁 編程語言 正文
基于 XML 的 AOP 開發
問題1:在通知方法中如何定義切入點表達式?
問題2:如何配置切面?
問題3:在配置類上如何開啟AOP注解功能?
1.1 快速入門
①導入 AOP 相關坐標
②創建目標接口和目標類(內部有切點)
③創建切面類(內部有增強方法)
④將目標類和切面類的對象創建權交給 spring
⑤在 applicationContext.xml 中配置織入關系
⑥測試代碼
1.1.1實現步驟
第一步 導入 AOP 相關坐標
<!--導入spring的context坐標,context依賴aop-->
<dependency>
?<groupId>org.springframework</groupId>
?<artifactId>spring-context</artifactId>
?<version>5.0.5.RELEASE</version>
</dependency>
<!-- aspectj的織入 -->
<dependency>
?<groupId>org.aspectj</groupId>
?<artifactId>aspectjweaver</artifactId>
?<version>1.8.13</version>
</dependency>
第二步 創建目標接口和目標類(內部有切點)
/*
? ?目標接口
*/
public interface TargetInterface {
? ?public void method();
}
@Component
public class Terget implements TargetInterface {
? ?@Override
? ?public void method() {
? ? ? ?System.out.println("Target 正在運行中....");
? }
}
第三步 創建切面類(內部有增強方法)
public class MyAspect {
? ?//前置增強方法
? ?public void before(){
? ? ? ?System.out.println("前置代碼增強.....");
? }
}
導入aop命名空間
第四步 在 applicationContext.xml 中配置織入關系
配置切點表達式和前置增強的織入關系
<aop:config>
? ?<!--引用myAspect的Bean為切面對象-->
? ?<aop:aspect ref="myAspect">
? ? ? ?<!--配置Target的method方法執行時要進行myAspect的before方法前置增強-->
? ? ? ?<aop:before method="before" pointcut="execution(public void com.by.aop.Target.method())"></aop:before>
? ?</aop:aspect>
</aop:config>
?
<!--優化代碼-->
<aop:config>
<aop:aspect ref="myAspect">
<aop:pointcut id="mypointcut" expression="execution(public void com.by.aop.Target.method())"/>
?
<aop:before method="before" pointcut-ref="mypointcut"></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();
? }
}
1.2 XML 配置 AOP 詳解
1.2.1 切點表達式的寫法
表達式語法:
execution([修飾符] 返回值類型 包名.類名.方法名(參數))
-
訪問修飾符可以省略
-
返回值類型、包名、類名、方法名可以使用星號* 代表任意
-
包名與類名之間一個點 . 代表當前包下的類,兩個點 .. 表示當前包及其子包下的類
-
參數列表可以使用兩個點 .. 表示任意個數,任意類型的參數列表
例如:
execution(public void com.by.aop.Target.method()) ?
execution(void com.by.aop.Target.*(..))
execution(* com.by.aop.*.*(..))
execution(* com.by..*.*(..))
execution(* *..*.*(..))
1.2.2.通知的類型
通知的配置語法:
<aop:通知類型 method=“切面類中方法名” pointcut=“切點表達式"></aop:通知類型>
通知執行順序
1.2.3 切點表達式的抽取
當多個增強的切點表達式相同時,可以將切點表達式進行抽取,在增強中使用 pointcut-ref 屬性代替 pointcut 屬性來引用抽取后的切點表達式。
<aop:config>
? ?<!--引用myAspect的Bean為切面對象-->
? ?<aop:aspect ref="myAspect">
? ? ? ?<aop:pointcut id="myPointcut" expression="execution(* com.by.aop.*.*(..))"/>
? ? ? ?<aop:before method="before" pointcut-ref="myPointcut"></aop:before>
? ?</aop:aspect>
</aop:config>
1.3 知識要點
-
aop織入的配置
<aop:config>
? ?<aop:aspect ref=“切面類”>
? ? ? ?<aop:before method=“通知方法名稱” pointcut=“切點表達式"></aop:before>
? ?</aop:aspect>
</aop:config>
-
通知的類型:前置通知、后置通知、環繞通知、異常拋出通知、最終通知
-
切點表達式的寫法:
execution([修飾符] 返回值類型 包名.類名.方法名(參數))
2.基于注解的 AOP 開發
2.1 AOP案例思路分析
-
案例設定:測定接口執行效率
-
簡化設定:在接口執行前輸出當前系統時間
-
開發模式:XML or ==注解==
-
思路分析:
-
導入坐標(pom.xml)
-
制作連接點方法(原始操作,dao接口與實現類)
-
制作共性功能 (通知類與通知)
-
定義切入點
-
綁定切入點與通知關系(切面)
-
2.2 AOP入門案例實現
【第二步】定義dao接口與實現類
public interface BookDao {
? ?public void save();
? ?public void update();
}
@Repository
public class BookDaoImpl implements BookDao {
? ?@Override
? ?public void save() {
? ? ? ?System.out.println(System.currentTimeMillis());
? ? ? ?System.out.println("book dao save ...");
? }
? ?@Override
? ?public void update() {
? ? ? ?System.out.println("book dao update ...");
? }
}
【第三步】定義通知類,制作通知方法
//通知類必須配置成Spring管理的bean
@Component
public class MyAdvice {
? ?public void method(){
? ? ? ?System.out.println(System.currentTimeMillis());
? }
}
【第四步】定義切入點表達式、配置切面(綁定切入點與通知關系)
//通知類必須配置成Spring管理的bean
@Component
//設置當前類為切面類類
@Aspect
public class MyAdvice {
? ?//設置切入點,@Pointcut注解要求配置在方法上方
? ?@Pointcut("execution(void com.by.dao.BookDao.save())")
? ?public void pt(){
?
? }
? ?//設置在切入點pt()的前面運行當前操作(前置通知)
? ?@Before("pt()")
? ?public void method(){
? ? ? ?System.out.println(System.currentTimeMillis());
? }
}
【第五步】在配置類中進行Spring注解包掃描和開啟AOP功能
@Configuration
@ComponentScan("com.by")
//開啟注解開發AOP功能
@EnableAspectJAutoProxy
public class SpringConfig {
}
測試類和運行結果
public class App {
? ?public static void main(String[] args) {
? ? ? ?ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
? ? ? ?BookDao bookDao = ctx.getBean(BookDao.class);
? ? ? ?bookDao.update();
? }
}
3. 注解+配置文件結合案例
基于注解+配置的aop開發步驟:
①創建目標接口和目標類(內部有切點)
②創建切面類(內部有增強方法)
③將目標類和切面類的對象創建權交給 spring
④在切面類中使用注解配置織入關系
⑤在配置文件中開啟組件掃描和 AOP 的自動代理
⑥測試
3.1 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.by.aop.*.*(..))")
? ?public void before(){
? ? ? ?System.out.println("前置代碼增強.....");
? }
}
第五步 在配置文件中開啟組件掃描和 AOP 的自動代理
<!--組件掃描-->
<context:component-scan base-package="com.by.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();
? }
}
4. AOP工作流程【理解】
什么是目標對象?什么是代理對象?
4.1 AOP工作流程
-
Spring容器啟動
-
讀取所有切面配置中的切入點
-
初始化bean,判定bean對應的類中的方法是否匹配到任意切入點
-
匹配失敗,創建原始對象
-
匹配成功,創建原始對象(目標對象)的代理對象
-
-
獲取bean執行方法
-
獲取的bean是原始對象時,調用方法并執行,完成操作
-
獲取的bean是代理對象時,根據代理對象的運行模式運行原始方法與增強的內容,完成操作
-
4.2 AOP核心概念
目標對象(Target):被代理的對象,也叫原始對象,該對象中的方法沒有任何功能增強。
代理對象(Proxy):代理后生成的對象,由Spring幫我們創建代理對象。
4.3 在測試類中驗證代理對象
public class App {
? ?public static void main(String[] args) {
? ? ? ?ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
? ? ? ?BookDao bookDao = ctx.getBean(BookDao.class);
? ? ? ?bookDao.update();
//打印對象的類名
? ? ? ?System.out.println(bookDao.getClass());
? }
}
回顧切入點表達式
5.1 語法格式
-
切入點:要進行增強的方法
-
切入點表達式:要進行增強的方法的描述方式execution(void com.by.dao.BookDao.update())execution(void com.by.dao.impl.BookDaoImpl.update())
-
描述方式一:執行com.by.dao包下的BookDao接口中的無參數update方法
-
描述方式二:執行com.by.dao.impl包下的BookDaoImpl類中的無參數update方法
-
-
切入點表達式標準格式:動作關鍵字(訪問修飾符 返回值 包名.類/接口名.方法名(參數) 異常名)execution(public User com.by.service.UserService.findById(int))
-
動作關鍵字:描述切入點的行為動作,例如execution表示執行到指定切入點
-
訪問修飾符:public,private等,可以省略
-
返回值:寫返回值類型
-
包名:多級包使用點連接
-
類/接口名:
-
方法名:
-
參數:直接寫參數的類型,多個類型用逗號隔開
-
異常名:方法定義中拋出指定異常,可以省略
-
5.2 通配符
目的:可以使用通配符描述切入點,快速描述。
-
:單個獨立的任意符號,可以獨立出現,也可以作為前綴或者后綴的匹配符出現
匹配com.by包下的任意包中的UserService類或接口中所有find開頭的帶有一個參數的方法
execution(public * com.by.*.UserService.find*(*))
-
.. :多個連續的任意符號,可以獨立出現,常用于簡化包名與參數的書寫
匹配com包下的任意包中的UserService類或接口中所有名稱為findById的方法
execution(public User com..UserService.findById(..))
-
+:專用于匹配子類類型
execution(* *..*Service+.*(..))
5.3 書寫技巧
-
所有代碼按照標準規范開發,否則以下技巧全部失效
-
描述切入點通==常描述接口==,而不描述實現類
-
訪問控制修飾符針對接口開發均采用public描述(==可省略訪問控制修飾符描述==)
-
返回值類型對于增刪改類使用精準類型加速匹配,對于查詢類使用*通配快速描述
-
==包名==書寫==盡量不使用..匹配==,效率過低,常用*做單個包描述匹配,或精準匹配
-
==接口名/類名==書寫名稱與模塊相關的==采用*匹配==,例如UserService書寫成*Service,綁定業務層接口名
-
==方法名==書寫以==動詞==進行==精準匹配==,名詞采用匹配,例如getById書寫成getBy,selectAll書寫成selectAll
-
參數規則較為復雜,根據業務方法靈活調整
-
通常==不使用異常==作為==匹配==規則
原文鏈接:https://blog.csdn.net/qq_52963857/article/details/131550900
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-11-16 Python加載文件內容的兩種實現方式_python
- 2023-02-07 C#實現加密exe文件_C#教程
- 2022-09-21 Flutter實現資源下載斷點續傳的示例代碼_Android
- 2022-06-18 android?ScrollView實現水平滑動回彈_Android
- 2022-07-12 Linux系統下的時區配置管理
- 2022-06-16 golang?gorm實現get請求查詢案例測試_Golang
- 2022-05-02 Python的os包與os.path模塊的用法詳情_python
- 2022-03-20 詳解C語言對字符串處理函數的實現方法_C 語言
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支