1. 程式人生 > >Spring的第三天AOP之xml版

Spring的第三天AOP之xml版

Spring的第三天AOP之xml版

ssm框架  spring 

AOP介紹

AOP(Aspect Oriented Programming),面向切面程式設計。它出來的目的並不是去取代oop,而是對它的完善和補充。在oop中,人們的是去定義縱向的關係,但是會出現一個問題:在程式中,日誌程式碼往往是橫向的地散佈在各種物件層次中,而在oop的模式設計中,導致了大量重複工作的程式碼。

可以這樣說:oop是面向名詞領域,AOP是面向動詞領域。AOP適合通用的工作,不適合個性化的工作。

圖來自網路,侵刪



在AOP中,我們將那些與多個類相關的行為放在一起變成一個模組,命名為Aspect【切面】。講個故事:

村裡來了一個通告,以前是到每家每戶去通知,假如通告進行了改變,又要重新進行通知,然後村裡面的人覺得太麻煩了,就做了一個聲音傳輸管道,每當有通告來的時候,村長就選擇要通知的,告訴他們某個時間去做通告裡面的東西,然後開啟管道進行通知。

  • 通告:通知(Advice)

    就是你想要的東西,比如說日誌,事物。

  • 人:PointCut【切入點】

    切入點裡面定義了Advice發生的地點,例如某個類或方法的名稱,為被切的地方。

  • 時間:Joinpoint【連線點】

    連線點就是告訴程式什麼時候去使用通知,例如當方法被呼叫時,或者是異常丟擲時。

  • 村長:Proxy【代理】
    Proxy不能算是AOP的家庭成員,它是一個管理部門,管理AOP如何融入OOP,是AOP的實踐者。同時AOP的代理離不開spring的IOC容器。在Spring Framework中,AOP代理是JDK動態代理或CGLIB代理。

那麼什麼是切面呢?
切面其實就是Advice+PointCut,代表了切面的所有元素,而將切面織入程式碼中就是依靠Proxy

maven依賴

匯入Spring依賴和aop依賴

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.0.8.RELEASE</version>
    <type>pom</type>
</dependency>

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

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.1.4.RELEASE</version>
</dependency>

頭部檔案xmlns檔案配置

<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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

</beans>

類的java程式碼

package com.weno.pojo;

public class User {
      public void print(){
        System.out.println("我這是在執行一個方法");
        throw new RuntimeException("我故意的報錯");
    }

    public String msg(){
        return "竟然有返回值";
    }
}

建議類:

package com.weno.aop;

    public void beforeMethod(){
        System.out.println("一千年以前");
    }

    public void afterMethod(){
        System.out.println("一千年以後");
    }
    
    public void returnMethod(Object rvt){
        System.out.println("返回值>>>>>>"+rvt);
        System.out.println("方法返回");
    }

    public void errorMethod(){
        System.out.println("程式竟然報錯了");
    }
}

xml版本的使用

首先先說一下切入點,切入點分為:

  • 前置通知:在連線點之前執行但無法阻止執行流程進入連線點的建議(除非它引發異常,該異常將中斷當前方法鏈的執行而返回)。

  • 後置通知:在連線點正常完成後執行的建議(例如,如果方法返回而不丟擲異常)。

  • 異常通知:如果方法通過丟擲異常退出,則執行建議。

  • 後置最終通知:無論連線點退出的方式(正常或異常返回),都要執行建議。

  • 環繞通知:環繞在連線點處的方法所執行的通知,環繞通知可以在方法呼叫之前和之後自定義任何行為,並且可以決定是否執行連線點處的方法、替換返回值、丟擲異常等等。環繞通知還需要負責決定是繼續處理join point(呼叫ProceedingJoinPoint的proceed方法)還是中斷執行。

前置通知,後置通知,異常通知,返回通知

<bean class="com.weno.pojo.User" id="user"/>
<bean class="com.weno.aop.Method" id="method"/>

<aop:config>
    <!--定義一個切面-->
    <aop:aspect ref="method">

        <!--切點,定義切點的id exexution後面寫要切入的地點:在print這個方法進行切-->
        <aop:pointcut id="positon" expression="execution(* com.weno.pojo.User.print())"/>
        <!-- 切的時間 method表示切的方法 -->
        <!-- beforeMethod 在執行方法之前切入 -->
        <aop:before method="beforeMethod" pointcut-ref="positon"/>
        <!-- 在執行方法之後切入 -->
        <aop:after method="afterMethod" pointcut-ref="positon"/>
        <!-- 在方法報錯的時候切入 -->
        <aop:after-throwing method="errorMethod" pointcut-ref="positon"/>
        <!-- 在方法有返回值的時候切 
             同時可以加上returning,將值傳給returnMethod()方法
        -->
        <aop:after-returning method="returnMethod" returning="rvt" pointcut="execution(* com.weno.pojo.User.msg())"/>
    </aop:aspect>
</aop:config>

測試程式碼一:

@Test
public void m01(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/spring-test1.xml");
    // 在這裡,如果直接通過new例項化User,那麼aop功能將失效,因為AOP是要在spring IOC容器裡面實現的
    User user = ctx.getBean("user",User.class);
    user.print();
}

輸出結果

一千年以前
我這是在執行一個方法
一千年以後
程式竟然報錯了

測試程式碼二:

@Test
public void m03(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/spring-test1.xml");
    User user = ctx.getBean("user",User.class);
    user.msg();
}

結果:

返回值>>>>>>竟然有返回值
方法返回

環繞通知

環繞通知是所有通知型別中功能中最為強大的,能夠全面地控制連線點,甚至能夠控制方法是否執行,同時,他還可以實現before和after的功能。

切面程式的程式碼

public void aroundMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

    //允許程式進行執行
    proceedingJoinPoint.proceed();
}

public void aroundMethod2(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    //允許程式進行執行,並將其引數進行改變。
    proceedingJoinPoint.proceed(new String[]{"你最帥"});
}

被切的程式

public void msg1(){
    System.out.println("這是米有引數的msg");
}

public void msg2(String msg){
    System.out.println("進行執行方法輸出"+msg);
}

xml檔案配置

<aop:around method="aroundMethod" pointcut="execution(* com.weno.pojo.User.msg1())"/>
<aop:around method="aroundMethod2" pointcut="execution(* com.weno.pojo.User.msg2(..))"/>

測試檔案


@Test
public void m04() {

    ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/spring-test1.xml");
    User user = ctx.getBean("user", User.class);

    user.msg1();
    user.msg2("我好帥");
}

結果

這是米有引數的msg
//在這裡面,引數進行了改變,由我好帥變成了你最帥
進行執行方法輸出你最帥

JoinPoint的神奇之處

官方文件

這個是官方文件擷取過來的

使用上面的那個例子來獲得引數:

public void aroundMethod2(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    Object[] args = proceedingJoinPoint.getArgs();
        System.out.println(Arrays.toString(args));
    //允許程式進行執行,並將其引數進行改變。
    proceedingJoinPoint.proceed(new String[]{"你最帥"});
}

輸出結果當然是:

這是米有引數的msg
[我好帥]
進行執行方法輸出你最帥

當然,如果你將Object[] args = proceedingJoinPoint.getArgs(); System.out.println(Arrays.toString(args));放在後面,那輸出引數當然就變成了[你最帥]。

基本資料型別和包裝類對於execution嚴格區分

首先先簡單的介紹一下execution,先定義一個表示式:

execution(* com.weno...(..))

在這裡面

識別符號 含義
execution 表示式的主體
第一‘*’號 表示返回值的型別,*號代表任意型別
com.weno 代表包,被切的地方
包後面的‘..’ 代表當前包及其子包
第二個‘*’號 代表類,*號代表所有類
第三個‘*’號 代表方法,‘*’代表任意方法

相關推薦

SpringAOPxml

Spring的第三天AOP之xml版 ssm框架  spring  AOP介紹 AOP(Aspect Oriented Programming),面向切面程式設計。它出來的目的並不是去取代oop

SpringAOP註解

Spring的第四天AOP之註解版 ssm框架  spring  在上一篇部落格中,介紹了Spring的AOP的xml版本的使用,在這篇部落格中,我將介紹一下,註解版的使用。 常用註解

SpringSpringAOP的註解開發、Spring的宣告式事務、JdbcTemplate

目錄 1.Spring的AOP基於AspectJ的註解開發 1.1Spring基於ApsectJ的註解的AOP開發 1.1.1建立專案,引入jar包 1.1.2引入配置檔案 1.1.3編寫目標類並配置 1.1.4編寫切面類並配置 1.1.5使用註解的AOP物件目標類進

SpringSpringAOP的註解開發、Spring的聲明式事務、JdbcTemplate。

spec template ntc 整合 roman 清晰 定義 method 延伸 1.1 上次課內容回顧 l Spring的IOC的註解開發 n 註解的入門 u 引入aop的包 u 引入context約束 l <context:com

通向架構師的道路(apache效能調優

在前兩天的學習中我們知道、瞭解並掌握了Web Server結合App Server實現單向Https的這樣的一個架構。這個架構是一個非常基礎的J2ee工程上線佈署時的一種架構。在前兩天的教程中,還講述了Http伺服器、App Server的最基本安全配置(包括單向htt

######Spring5ssh整合(註解)難理解知識點:【自定義 方法加註解的方式】給dao注入sessionFactory屬性+【搞清@Autowared和@Resource含義】

===【方法加註解的方式】給dao注入sessionFactory屬性(繼承父類的屬性),第一次見!===具體怎麼用的,看原始碼。(後面有寫) 以前都是屬性+註解注入屬性。 [email protected]和@Resource到底是幹嘛的? 剛學IOC時可能能

c語言學習選擇結構程序設計(

c語言 選擇結構為了增加理解,寫的幾個小程序1:判斷三角形的成立以及輸出最大邊 練習前三種語句#include <stdio.h> int main() { int a,b,c; printf("請輸入三角形三邊長(邊為整數,不能輸入負數):"); scanf("%d%d%d", &a ,

XML&反射

xml一、XML1 什麽是XMLXML全稱為Extensible Markup Language,意思是可擴展的標記語言。XML語法上和HTML比較相似,但HTML中的元素是固定的,而XML的標簽是可以由用戶自定義的2、應用常見<1>配置文件<2>存放數據3、XML語法<1>

python學習路--一個簡單的腳本

tro 說明 .py else zipfile rect dylib 環境 cef 現在有一個需求:把某個目錄下的文件備份到指定到另外一個目錄下,而且壓縮後文件為zip文件 # -*- coding:utf-8 -*- #! /usr/bin/python # Filena

struts2框架文件上傳(參考學習筆記)

input 允許 jakarta ges too 文件的 ESS dir 參數 上傳 1. 上傳對表單的要求 * method=post * enctype=multipart/form-data 2. 上傳對servlet要求 * getParameter()不能再使用!

struts2框架OGNL(參考學習筆記)

元素 eterm 進行 oot 結構 保存 pass 一個表 this ognl 1. 什麽是ognl 對象圖導航語言 Struts內置的表達式語言,它比EL要強大很多。 ------------------ 2. 單獨學習ognl * EL它操作的數據來自於:四大域

java學習路---------

今天主要就是陣列的基本概念 陣列:例子            int  arr[] = new int[3];      &nb

python學習的21模組pickle、json、xml、shelve、configparser

一、pickle  *** 1、作用;專門用於python語言的序列化 PS;(1)什麼是序列化?                指的是將記憶體中的資料結構轉化為一種中間格式,並存儲到硬碟上   &nb

(2)docker 安裝詳細手工(yum)

應用 docker環境部署 1 主機環境需求 uname -a 主要檢視核心是否符合Docker的需求 2 部署docker 我們從網路環境、安全配置、主機名規劃、軟體源配置、基礎軟體安裝、docker安裝六個方面來學習 網路環境: 關閉NetworkManag

資料庫基礎 四張圖理解資料庫張 資料庫連線 JDBC 理解 多表操作(附帶相關資源)

JDBC JDBC: 概述: Java Data Base Connectivity,Java資料庫連線 就是Java程式碼操作不同資料庫(DBMS)。 JDBC就是Java定義的用來操作不同資料庫的規範,本質就是一些介面和類。

《JavaScript高階程式設計(3)》 引用型別

/*====================================================== *@author wf_Huang *@Time 2018/9/18 20:06 *=======================================

LeetCode刷題路(

10. 正則表示式匹配 給定一個字串 (s) 和一個字元模式 §。實現支援 ‘.’ 和 ‘*’ 的正則表示式匹配。 ‘.’ 匹配任意單個字元。 ‘*’ 匹配零個或多個前面的元素。 匹配應該覆蓋整個字串 (s) ,而不是部分字串。 說明: s 可能為空,且只包含

python 資料型別方法

# list # [element, , , ] element 數字 字串 列表 bool 等等都可以 # str 字串集合 list 容器 # 取範圍 得到list li = [1, 2, 3, 4, 5, 6, 7] print(li, li[1:3]) for item in li:

spring cloud連載篇補充Zuul

由於Zuul的內容較多所以單獨列出一篇來講。全是乾貨,如果學到東西的,動動小手給點個推薦^_^  謝謝! 1. Router and Filter: Zuul(路由和過濾:Zuul) 路由是微服務架構不缺少的一部分。例如“/”可能對映到web服務,“/api/users”對映到使用者管理服務,而“/api/s

前端學習JavaScript

                                           Javascript基礎 一、Switch語句 Switch(變數){ case 1: 如果變數和1的值相同,執行該處程式碼 break;