系統學習SpringFramework:Spring AOP

本篇內容包括:Spring AOP 概述(AOP 簡介、AOP 為什么叫面向切面編程、AOP 主要用來解決的問題 和 AOP 的相關術語)、Spring AOP Demo(xml 方式、注解方式)以及相關知識點(JDK 動態代理和 CGLIB 代理、Spring AOP 和 AspectJ AOP、@Aspect、@Pointcut、@Around 注解)等內容!

一、Spring AOP 概述

1、AOP 簡介

AOP(Aspect oriented programming),即面向切面編程,它是一個編程范式,是 OOP(面向對象編程)的一種延續,目的就是提高代碼的模塊性。

Spring AOP 基于動態代理的方式實現,如果是實現了接口的話就會使用 JDK 動態代理,反之則使用 CGLIB 代理,Spring中 AOP 的應用主要體現在 事務、日志、異常處理等方面,通過在代碼的前后做一些增強處理,可以實現對業務邏輯的隔離,提高代碼的模塊化能力,同時也是解耦。Spring主要提供了 Aspect 切面、JoinPoint 連接點、PointCut 切入點、Advice 增強等實現方式。

2、AOP 為什么叫面向切面編程

切 :指的是橫切邏輯,原有業務邏輯代碼不動,只能操作橫切邏輯代碼,所以面向橫切邏輯

面 :橫切邏輯代碼往往要影響的是很多個方法,每個方法如同一個點,多個點構成一個面。這里有一個面的概念

3、AOP 主要用來解決的問題

例如:現有三個類,HorsePigDog,這三個類中都有 eat 和 run 兩個方法。

通過 OOP 思想中的繼承,我們可以提取出一個 Animal 的父類,然后將 eat 和 run 方法放入父類中,HorsePigDog通過繼承Animal類即可自動獲得 eat()run() 方法。這樣將會少些很多重復的代碼。

OOP 編程思想可以解決大部分的代碼重復問題。但是有一些問題是處理不了的。比如在父類 Animal 中的多個方法的相同位置出現了重復的代碼,OOP 就解決不了。這部分重復的代碼,一般統稱為橫切邏輯代碼。

橫切邏輯代碼存在的問題:

  • 代碼重復問題
  • 橫切邏輯代碼和業務代碼混雜在一起,代碼臃腫,不變維護

AOP 就是用來解決這些問題的:AOP 另辟蹊徑,提出橫向抽取機制,將橫切邏輯代碼和業務邏輯代碼分離,代碼拆分比較容易,難的是如何在不改變原有業務邏輯的情況下,悄無聲息的將橫向邏輯代碼應用到原有的業務邏輯中,達到和原來一樣的效果

AOP 主要用來解決:在不改變原有業務邏輯的情況下,增強橫切邏輯代碼,根本上解耦合,避免橫切邏輯代碼重復。

4、AOP 的相關術語

  1. 連接點(Joinpoint):所謂連接點是指那些被攔截到的點。在spring中,這些點指的是方法,因為spring只支持方法類型的連接點。
  2. 切入點(Pointcut):切入點是指我們要對哪些連接點(Joinpoint)進行攔截
  3. 通知/增強(Advice):所謂通知是指攔截到Joinpoint之后要做的事情,通知分為前置通知,后置通知,異常通知,最終通知,環繞通知(切面要完成的功能)。
  4. 織入(Weaving):是指把增強應用到目標對象來創建新的代理對象的過程。spring采用動態代理織入,而AspectJ采用編譯期織入和類裝載期織入。
  5. 切面(Aspect):是切入點和通知(引介)的結合
  6. 代理(Proxy):一個類被AOP織入增強后,就產生了一個結果代理類
  7. 目標對象(Target):代理的目標對象

二、Spring AOP Demo

1、xml配置方式

# 引入依賴

 				<!-- 模塊構建在 spring-core 和 spring-Beans 之上。它繼承了 Bean 模塊的特性,并添加了對國際化、事件傳播、資源加載透明化的支持 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.22</version></dependency>

# 配置 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/beanshttp://www.springframework.org/schema/beans/spring-beans-4.2.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.2.xsd"><bean id="aopTank" class="designpattern.aop.v1.AopTank"/><bean id="aopMethod" class="designpattern.aop.v1.AopMethod"/><aop:config><aop:aspect id="time" ref="aopMethod"><aop:pointcut id="onmove" expression="execution(public void com.liziheng.demo.api.aop.demo.AopDog.*(..))"/><aop:before method="before" pointcut-ref="onmove"/><aop:after method="after" pointcut-ref="onmove"/></aop:aspect></aop:config></beans>

# 切入時添加方法

public class AopMethod {public void before() {System.out.println("before...");}public void after() {System.out.println("after...");}
}

# 被切入的類

public class AopDog {public void eat() {System.out.println("The dog is eating...");}public void drink() {System.out.println("The dog is drinking water...");}}

# 測試

public class Main {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("app.xml");AopDog dog = (AopDog) context.getBean("AopDog");tank.move();tank.voice();}
}

2、注解方式

# 引入依賴

        <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency>

# 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/beanshttp://www.springframework.org/schema/beans/spring-beans-4.2.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.2.xsd"><aop:aspectj-autoproxy/><bean id="aopTank" class="designpattern.aop.v1.AopTank"/><bean id="aopMethod" class="designpattern.aop.v1.AopMethod"/>
</beans>

# 切入時添加方法

public class AopMethod {@Before("execution(public void com.liziheng.demo.api.aop.demo.AopDog.*(..))")public void before() {System.out.println("before...");}@After("execution(public void com.liziheng.demo.api.aop.demo.AopDog.*(..))")public void after() {System.out.println("after...");}
}

# 被切入的類 同xml方式

# 測試 同xml方式


三、相關知識點

1、JDK 動態代理和 CGLIB 代理

JDK 動態代理主要是針對類實現了某個接口,AOP 則會使用 JDK 動態代理。他基于反射的機制實現,生成一個實現同樣接口的一個代理類,然后通過重寫方法的方式,實現對代碼的增強;

而如果某個類沒有實現接口,AOP 則會使用 CGLIB 代理。他的底層原理是基于 asm 第三方框架,通過修改字節碼生成成成一個子類,然后重寫父類的方法,實現對代碼的增強。

2、Spring AOP 和 AspectJ AOP

Spring AOP 基于動態代理實現,屬于運行時增強。

AspectJ 則屬于編譯時增強,主要有3種方式:

  1. 編譯時織入:指的是增強的代碼和源代碼我們都有,直接使用 AspectJ 編譯器編譯就行了,編譯之后生成一個新的類,他也會作為一個正常的 Java 類裝載到 JVM;
  2. 編譯后織入:指的是代碼已經被編譯成 class 文件或者已經打成 jar 包,這時候要增強的話,就是編譯后織入,比如你依賴了第三方的類庫,又想對他增強的話,就可以通過這種方式;
  3. 加載時織入:指的是在 JVM 加載類的時候進行織入。

總結下來的話,就是 Spring AOP 只能在運行時織入,不需要單獨編譯,性能相比 AspectJ 編譯織入的方式慢,而 AspectJ 只支持編譯前后和類加載時織入,性能更好,功能更加強大。

3、@Aspect、@Pointcut、@Around 注解

  • @Pointcut表示一個切入點,value表示切入點的作用范圍
  • @Aspect 表示申明一個切面
    • @Around,環繞增強:方法正常之前的前后調用
    • @Before,前置增強:方法執行前調用
    • @After,后置 final 增強:不管方法正常退出還是一場都會執行
    • @AfterReturning,后置增強:方法正常退出時執行
    • @AfterThowing,異常拋出增強:方法拋異常時執行

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/535491.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/535491.shtml
英文地址,請注明出處:http://en.pswp.cn/news/535491.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

rowid

ROWID的格式rowidOOOOOOFFFBBBBBBRRR說明數據對象號相對文件號數據塊號行號 上述表格是Oracle 9i及以上版本數據庫中的rowid格式: 6位對象號3位相對文件號6位數據塊號3位行號&#xff0c;是一個18位的64進制值。這個18位的64進制值在數據庫內卻是以10個bytes合計80個bit的二進制…

git和gitlab安裝

1.下載git最新包 https://mirrors.edge.kernel.org/pub/software/scm/git/ 將最新包上傳至服務器/home目錄 tar -Jxvf 解壓 進入git目錄 ./configure --prefix/usr/local/git make make install 錯誤解決&#xff1a;Cant locate ExtUtils/MakeMaker.pm in INC yum i…

系統學習SpringFramework:循環依賴與三級緩存

本篇內容包括&#xff1a;Spring 中的循環依賴問題&#xff08;包括 Spring 中的循環依賴問題和Spring 中的循環依賴的 5 種場景的介紹&#xff09;、Spring 三級緩存介紹、4 個 Spring 無法自動解決的循環以來場景以及其對應的手動解決方式。 一、Spring 中的循環依賴問題 1、…

oracle安裝需要的包列表

redhat7.5安裝圖形界面&#xff1a; [rootwwyt ~]# rpm -ivh --nodeps --force xorg-x11-font* [rootwwyt ~]# mount -o loop -t iso9660 rhel-server-7.5-x86_64-dvd.iso /media/iso/ [rootwwyt ~]# cat /etc/yum.repos.d/my.repo [base] nameredhat7.5 baseurlfile:///m…

深入理解Java虛擬機:Java類的加載機制

本篇內容包括&#xff1a;Java 類的加載機制&#xff08;Jvm 結構組成、Java 類的加載&#xff09;、類的生命周期&#xff08;加載-驗證-準備-解析-初始化-使用-卸載&#xff09;、類加載器 以及 雙親委派模型。 一、Java 類的加載機制 1、 Jvm 結構組成 Jvm 整體組成可分為…

新版谷歌瀏覽器開啟Flash支持

瀏覽器地址欄中輸入chrome://version查看Chrome瀏覽器、Flash插件的版本信息。 Chrome 69.0-70.0版本Chrome 71.0-74.0及以后版本谷歌瀏覽器地址欄中輸入【chrome://flags/#enable-ephemeral-flash-permission】&#xff0c;將【Enable Ephemeral Flash Permissions】從【Defau…

深入理解Java虛擬機:Java垃圾回收機制

本篇內容包括&#xff1a;JAVA 垃圾回收機制概述、有哪些內存需要回收、如何回收&#xff08;標記-清除、標記-整理&#xff08;標記-清除-壓縮&#xff09;、復制&#xff08;標記-復制-清除&#xff09;、分代收集等算法&#xff09; 以及 何時進行垃圾回收等內容&#xff01…

深入理解Java虛擬機:Java垃圾回收器

本篇內容包括&#xff1a;7 種 Jvm 垃圾回收器的介紹、對比 以及 對應的 Jvm 參數設置&#xff0c;這 7 種包括了&#xff1a;Serial、ParNew 以及 Parallel Scavenge 三種新生代回收器 和 &#xff1a;Serial Old、Parallel Old 以及 CMS 三種老年代回收器&#xff0c;此外還有…

oracle跨越千年處理

如果指定的兩位年份0-4950-99 如果當前 的兩位年 份是 0-49返回的日期是當前世紀返回的日期是上個世紀50-99返回的日期是下個世紀返回的日期是當前世紀 current yearSpecified DateRR FormatYY Format199527-OCT-9519951995199527-OCT-171951917200127-OCT-1720012017200127-OC…

網絡協議:什么是網絡分層的七四五

本篇內容包括&#xff1a;網絡分層七層、五層、四層網絡協議概念的介紹&#xff0c;IOS 體系結構的介紹與構成、TCP/IP體系結構的簡介及與IOS體系的關系 以及五層體系結構的介紹。 一、七層、五層、四層網絡協議概念 1、關于網絡協議 網絡協議&#xff0c;即是指計算機網絡中…

查看表空間相關命令

默認表空間數據文件大小根據DATA BLOCKS的大小有關&#xff0c;默認最大為32GB表空間達到32G&#xff0c;只能增加數據文件alter tablespace 表空間名 add datafile 數據文件路徑‘ size 500m autoextend on next 100m maxsize 10000M;未達到32G&#xff0c;修改數據文件的擴展…

網絡協議:一文搞懂Socket套接字

本篇內容包括&#xff1a;Socket 套接字的簡介、Socket 套接字的分類、Java 中的 Socket 即 java.net.ServerSocket、java.net.Socket 的使用&#xff0c;以及Java 使用套接字 Scoket 編程的Demo。 一、Socket 簡介 TCP&#xff08;傳輸控制協議&#xff09;是一種面向連接的、…

RESETLOGS

使用resetlogs選項&#xff0c;會把當前的日志序號&#xff08;log sequence number&#xff09;重設為1&#xff0c;并拋棄所有日志信息。在以下條件時需要使用resetlogs選項&#xff1a; 在不完全恢復&#xff08;介質恢復&#xff09;&#xff1b; 使用備份控制文件。 使…

網絡協議:透徹解析HTTP協議

本篇內容包括&#xff1a;HTTP 協議定義及其特點概述、關于 URL 定義及分類概述、Request 請求、Response 響應 以及 瀏覽器訪問一個網站的全過程 等內容… 一、HTTP 協議概述 HTTP&#xff08;HyperText Transfer Protocol&#xff09; 即 超文本傳輸協議&#xff0c;它是一種…

oracle參數文件和口令文件

外部 審核 口令&#xff1a;記錄超級用戶的用戶名和口令&#xff0c;做sys用戶的安全審核 oracle9以后全部使用sys登錄&#xff0c;但需要使用as sysdba &#xff0c;之前版本需要使用internal o7字典打開 只要用戶和密碼存在于口令文件&#xff0c;就可以以sysdba登錄&#…

innobackup備份恢復實操步驟--gtid復制(1)(1)

首先在主庫進行備份&#xff1a; 備份命令&#xff1a; Innobackupex --defaults-file/app/dbcluster/sgrdb/mysql/my19103.cnf --no-timestamp --userdbscale --passwordS6000dbscale --host10.157.43.224 --port19103 /data/backup 如果使用setsid&#xff1a; setsid …

Redis系列:Redis的概述與安裝

Redis(Remote Dictionary Server) 是一個使用 C 語言編寫的&#xff0c;開源的&#xff08;BSD許可&#xff09;高性能非關系型&#xff08;NoSQL&#xff09;的鍵值對數據庫。 本篇內容包括&#xff1a;Redis 簡介&#xff08;為什么快&#xff1f;為什么單線程&#xff1f;優…

安裝LibreOffice和字體

#/bin/bash # Check if user is root if [ $(id -u) ! "0" ]; thenecho "Error: You must be root to run this script, please use root"exit 1 fi echo 安裝LibreOffice cd /home/ tar -zxvf LibreOffice_6.3.3_Linux_x86-64_rpm.tar.gz cd /home/LibreO…

xtrabackup備份腳本

#!/bin/sh #備份主機 remote_ip100.0.132.160 Master_ip100.20.132.158 VIP100.20.132.166 #備份用戶 userroot #密碼 password00000 # 返回年月日 backup_datedate %F # 返回時分秒 backup_timedate %H-%M-%S # 返回今天是這周的第幾天 backup_week_daydate %u backup_ok0 #備…