1. 程式人生 > >spring AOP和通知

spring AOP和通知

1.  spring的通知

1.1.  AOP的概念

切面(Aspect):一個關注點的模組化,這個關注點可能會橫切多個物件。事務管理是J2EE應用中一個關於橫切關注點的很好的例子。在Spring AOP中,切面可以使用基於模式或者基於註解的方式來實現。

連線點(Joinpoint):在程式執行過程中某個特定的點,比如某方法呼叫的時候或者處理異常的時候。在Spring AOP中,一個連線點總是表示一個方法的執行。

通知(Advice):在切面的某個特定的連線點上執行的動作。其中包括了“around”、“before”和“after”等不同型別的通知。許多AOP框架(包括Spring)都是以攔截器做通知模型,並維護一個以連線點為中心的攔截器鏈。

切入點(Pointcut):匹配連線點的斷言。通知和一個切入點表示式關聯,並在滿足這個切入點的連線點上執行(例如,當執行某個特定名稱的方法時)。切入點表示式如何和連線點匹配是AOP的核心:Spring預設使用AspectJ切入點語法。

引入(Introduction):用來給一個型別宣告額外的方法或屬性(也被稱為連線型別宣告(inter-type declaration))。Spring允許引入新的介面(以及一個對應的實現)到任何被代理的物件。例如,你可以使用引入來使一個bean實現IsModified介面,以便簡化快取機制。

目標物件(Target Object): 被一個或者多個切面所通知的物件。也被稱做被通知(advised)物件。既然Spring AOP是通過執行時代理實現的,這個物件永遠是一個被代理(proxied)物件。

AOP代理(AOP Proxy):AOP框架建立的物件,用來實現切面契約(例如通知方法執行等等)。在Spring中,AOP代理可以是JDK動態代理或者CGLIB代理。

織入(Weaving):把切面連線到其它的應用程式型別或者物件上,並建立一個被通知的物件。這些可以在編譯時(例如使用AspectJ編譯器),類載入時和執行時完成。Spring和其他純Java AOP框架一樣,在執行時完成織入。

1.2.  通知

通知型別

介面

描述

Around

org.aopalliance.intercept.

MethodInterceptor

攔截對目標方法呼叫

Before

Org.springframework.aop.

MethodBeforeAdvice

在目標方法呼叫前呼叫

After

Org.springframework.aop.

AfterReturningAdvice

在目標方法呼叫後呼叫

Throws

Org.springframework.aop.

ThrowsAdvice

當目標方法丟擲異常時呼叫

1.2.1.  前置通知

Org.springframework.aop.MethodBeforeAdvice介面的程式碼如下:

public abstract interface MethodBeforeAdvice extends BeforeAdvice {

         public abstract void before(Method paramMethod,

                            Object[] paramArrayOfObject, Object paramObject) throws Throwable;

}

注意返回值的型別是void。前置通知可以在連線點執行之前插入自定義行為,但是不能修改連線點的返回值。如果一個前置通知丟擲異常,這將中止攔截器鏈的進一步執行。異常將沿著攔截器鏈向回傳播。如果異常是非強制檢查的(unchecked)或者已經被包含在被呼叫方法的throws宣告中,它將被直接返回給客戶端;否則它將由AOP代理包裝在一個非強制檢查異常中返回。

1.2.2.  後置通知

Org.springframework.aop.AfterReturningAdvice介面的程式碼如下:

public abstract interface AfterReturningAdvice extends AfterAdvice {

         public abstract void afterReturning(Object paramObject1,

                            Method paramMethod, Object[] paramArrayOfObject, Object paramObject2)

                            throws Throwable;

}

後置通知可以訪問返回值(但不能進行修改),被呼叫方法,方法引數以及目標物件。

1.2.3.  環繞通知

public abstract interface MethodInterceptor extends Callback {

         public abstract Object intercept(Object paramObject, Method paramMethod,

                            Object[] paramArrayOfObject, MethodProxy paramMethodProxy)

                            throws Throwable;

}

invoke()方法的MethodInvocation引數暴露了被呼叫的方法,目標連線點,AOP代理以及傳遞給方法的引數。invoke()方法應該返回呼叫的結果:即連線點的返回值。注意對MethodInvocation中proceed()方法的呼叫。這個方法繼續執行指向連線點的攔截器鏈並返回proceed()的結果。大多數攔截器會呼叫這個方法,返回一個值。然而,一個類似任意環繞通知的MethodInterceptor,可以返回一個不同的值或者丟擲一個異常而不是呼叫proceed方法。

1.2.4.  異常通知

如果連線點丟擲異常,異常通知(throwsadvice)將在連線點返回後被呼叫。 Spring提供型別檢查的異常通知(typed throws advice),這意味著org.springframework.aop.ThrowsAdvice介面不包含任何方法: 它只是一個標記介面用來標識所給物件實現了一個或者多個針對特定型別的異常通知方法。這些方法應當滿足下面的格式:

afterThrowing([Method, args, target], subclassOfThrowable)

只有最後一個引數是必須的。根據異常通知方法對方法及引數的需求,方法的簽名可以有一個或者四個引數。下面是一個異常通知的例子。

當一個RemoteException(包括它的子類)被丟擲時,下面的通知會被呼叫:

public class RemoteThrowsAdvice implements ThrowsAdvice {

    public void afterThrowing(RemoteException ex) throws Throwable {

                // Do something with remote exception

    }

            }

1.2.5.  通知使用例項

1)        使用新建eclipse新建一個java web工程,引入spring jar包

2)        新建一個實現了前置通知介面的類BeforeAdvice類

package com.morris.spring.aop;

import java.lang.reflect.Method;

import java.util.Arrays;

import org.springframework.aop.MethodBeforeAdvice;

public class BeforeAdvice implements MethodBeforeAdvice {

         public void before(Method paramMethod, Object[] paramArrayOfObject,

                            Object paramObject) throws Throwable {

                   System.out.println("。。。。前置通知開始。。。。");

                   System.out.println("要執行的方法:"+paramMethod.getName());

                   System.out.println("引數:"+Arrays.toString(paramArrayOfObject));

                   System.out.println("目標物件:"+paramObject);

                   System.out.println("。。。。前置通知結束。。。。");

         }

}

3)        新建一個實現了後置通知介面的類AfterAdvice

package com.morris.spring.aop;

import java.lang.reflect.Method;

import java.util.Arrays;

import org.springframework.aop.AfterReturningAdvice;

public class AfterAdvice implements AfterReturningAdvice {

         public void afterReturning(Object paramObject1, Method paramMethod,

                            Object[] paramArrayOfObject, Object paramObject2) throws Throwable {

                   System.out.println("後置通知開始。。。。");

                   System.out.println("返回值:"+paramObject1);

                   System.out.println("執行方法:"+paramMethod.getName());

                   System.out.println("引數:"+Arrays.toString(paramArrayOfObject));

                   System.out.println("目標物件:"+paramObject2);

                   System.out.println("後置通知結束。。。。");

         }

}

4)        新建一個實現了環繞通知介面的類RoundAdvice

package com.morris.spring.aop;

import java.lang.reflect.Method;

import java.util.Arrays;

import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

public class RoundAdvice implements MethodInterceptor {

         public Object invoke(MethodInvocation invocation) throws Throwable {

                   System.out.println("--環繞通知開始------");

                   Method method = invocation.getMethod();

                   System.out.println("執行的方法:" + method.getName());

                   Object[] parameters = invocation.getArguments();

                   System.out.println("引數:" + Arrays.toString(parameters));

                   Object obj = invocation.proceed();

                   System.out.println("--環繞通知結束-----");

                   return obj;

         }

}

5)        新建目標物件所需實現的介面IHello

package com.morris.spring.aop;

public interface IHello {

         String sayHello(String name);

}

6)        新建一個目標物件HelloImpl

package com.morris.spring.aop;

public class HelloImpl implements IHello {

         public String sayHello(String name) {

                   System.out.println("********執行目標方法***********");

                   return "Hello " + name;

         }

}

7)        編寫spring的配置檔案

<?xml version="1.0" encoding="UTF-8"?>

<!-- - Middle tier application context definition for the image database. -->

<beans xmlns="http://www.springframework.org/schema/beans"

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"

         xmlns:tx="http://www.springframework.org/schema/tx"

         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

                                     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

                                     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

         <!-- 前置物件 -->

         <bean id="beforeAdvice" class="com.morris.spring.aop.BeforeAdvice"></bean>

         <!-- 後置物件 -->

         <bean id="afterAdvice" class="com.morris.spring.aop.AfterAdvice"></bean>

         <!-- 環繞通知 -->

         <bean id="roundAdvice" class="com.morris.spring.aop.RoundAdvice"></bean>

         <!-- 目標物件 -->

         <bean id="hello" class="com.morris.spring.aop.HelloImpl"></bean>

         <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">

                   <!-- 引用目標物件 -->

                   <property name="target" ref="hello"></property>

                   <!-- 要代理的介面,目標物件實現的介面 -->

                   <property name="proxyInterfaces">

                            <list>

                                     <value>com.morris.spring.aop.IHello</value>

                            </list>

                   </property>

                   <!-- 攔截器,所有的通知 -->

                   <property name="interceptorNames">

                            <list>

                                     <value>beforeAdvice</value>

                                     <value>afterAdvice</value>

                                     <value>roundAdvice</value>

                            </list>

                   </property>

         </bean>

</beans>

8)        編寫測試類Test

package com.morris.spring.aop;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

         public static void main(String[] args) {

                   // 載入spring配置檔案

                   ApplicationContext applicationContext = new ClassPathXmlApplicationContext(

                                     "spring.xml");

                   // 獲得目標物件

                   IHello hello = (IHello) applicationContext.getBean("proxy");

                   // 執行目標物件方法

                   hello.sayHello("morris");

         }

}

執行結果如下:

。。。。前置通知開始。。。。

要執行的方法:sayHello

引數:[morris]

目標物件:[email protected]

。。。。前置通知結束。。。。

--環繞通知開始------

執行的方法:sayHello

引數:[morris]

********執行目標方法***********

--環繞通知結束-----

後置通知開始。。。。

返回值:Hello morris

執行方法:sayHello

引數:[morris]

目標物件:[email protected]

後置通知結束。。。。

相關推薦

spring AOP通知

1.  spring的通知 1.1.  AOP的概念 切面(Aspect):一個關注點的模組化,這個關注點可能會橫切多個物件。事務管理是J2EE應用中一個關於橫切關注點的很好的例子。在Spring AOP中,切面可以使用基於模式或者基於註解的方式來實現。 連線點(Joinp

spring-AOP通知顧問

多個 targe ges 配置 context color ive 後置 功能 通知和顧問都是切面的實現形式,其中通知可以完成對目標對象方法簡單的織入功能。 而顧問包裝了通知,可以讓我們對通知實現更加精細化的管理,讓我們可以指定具體的切入點。 通知分為前置通知,環繞通知及後

(13)Spring學習記錄---Spring_bean(AOP通知

    springaop   1.jar包 com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar co

Spring AOP前置通知後置通知

在Spring中啟用AspectJ註解支援   要在Spring應用中使用AspectJ註解,必須在classpath下包含AspectJ類庫:aopalliance.jar、aspectj.weaver.jar和spring-aspects.jar   將aop Schema新增到<beans>

Spring AOP高級——源碼實現(2)Spring AOP通知器(Advisor)與切面(Aspect)

color oaf 小麻煩 ntc tro sta ins pack package 本文例子完整源碼地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/Spring%20AO

面試中關於Spring AOP代理模式的那些事

我們知道,Spring 中 AOP 是一大核心技術,也是面試中經常會被問到的問題,最近我在網上也看到很多面試題,其中和 Spring AOP 相關的就有不少,這篇文章主要來總結下相關的技術點,希望對大家有用。 0. 幾個常見的問題 針對這一塊的東西,一般下面幾個問題面試官問的比較多: Spr

spring aop 003: 通知

package com.thereisnospon.spring.demo.course.imp.c004_aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.an

Spring Boot 中使用 Spring AOP AspectJ 來測量方法的執行時間

原文連結:https://dzone.com/articles/logging-average-method-execution-times-via-aspectj 作者:Murat Derman 譯者:Darren Luo 想要了解更多有關測量方法執行時間的資訊?檢視本教

Spring AOP返回通知&異常通知&環繞通知(二十二)

一、返回通知 無論連線點是正常返回還是丟擲異常, 後置通知都會執行. 如果只想在連線點返回的時候記錄日誌, 應使用返回通知代替後置通知. 在方法法正常結束受執行的程式碼;

Spring-AOPAspectJ的區別聯絡

AOP是Spring框架的重要組成部分。目前我所接觸的AOP實現框架有Spring AOP還有就是AspectJ(還有另外幾種我沒有接觸過)。我們先來說說他們的區別: AspectJ是一個比較牛逼的AOP框架,他可以對類的成員變數,方法進行攔截。由於 AspectJ

什麼是 Spring AOP 代理

https://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_9403056301388627935%22%7D&n_type=0&p_from=1  這是這篇部落格的來源,我個人覺得

求求你,下次面試別再問我什麼是 Spring AOP 代理了!

作者 | 倪升武 責編 | 胡巍巍 我們知道,Spring 中 AOP 是一大核心技術,也是面試中經常會被問到的問題,最近我在網上也看到很多面試題,其中和 Spring AOP 相關的就有不少,這篇文章主要來總結下相關的技術點,希望對大家有用

Spring AOP前置通知例項說明AOP相關概念

今天又看了下韓順平的SpringAOP的講解,講解的很透徹。仿照視訊自己使用下前置通知。 一、引出問題   有個介面TestServiceInter,有兩個實現方法TestService和Test2Service。他們都有sayHello();我們的需求是在呼叫這兩個方法之前,要先完成寫日誌的功能; 二

Spring AOP 環繞通知

Spring AOP的環繞通知和前置、後置通知有著很大的區別,主要有兩個重要的區別: 1)目標方法的呼叫由環繞通知決定,即你可以決定是否呼叫目標方法,而前置和後置通知是不能決定的,它們只是在方法的呼叫前後執行通知而已,即目標方法肯定是要執行的。joinPoint.proce

[轉]求求你,下次面試別再問我什麼是 Spring AOP 代理了!

求求你,下次面試別再問我什麼是 Spring AOP 和代理了! 倪升武 CSDN 1周前 作者 | 倪升武 責編 | 胡巍巍 我們知道,Spring 中 AOP 是一大核心技術,也是面試中經常會被問到的問題,最近我在網上也看到很多面

Spring AOP各種通知 以及執行順序

1.定義切面 </pre><pre name="code" class="java"><pre name="code" class="java">package test2; import org.aspectj.lang.JoinPo

使用AspectJ需要匯入Spring AOPAspectj相關jar包,新版本Spring框架,建議使用AspectJ方式開發AOP

Spring JDBC是Spring提供的持久層技術簡化JDBC API開發,使用上和Apache公司的DBUtils框架非常類似匯入必要jar包到工程目錄匯入Spring核心開發包到建立工程spring-beans-3.2.0.RELEASE.jarspring-conte

基於Spring AOPGroovy日誌模板配置的日誌記錄框架的二次實現與使用案例

一、專案地址 說明:本框架是基於koala-project(專案地址:http://git.oschina.net/openkoala/koala)中的koala-businesslog二次開發,因為koala-project已經很久沒有維護,對於一些

Spring aop 前置通知、後置通知、返回通知、 異常通知 、後置通知

  Spring AOP定義切面 Ⅰ 首先介紹一下寫Spring Aop思路  一、首先在專案中加入aop所需要的jar aopalliance-1.0.jar aspectjweaver-1.6.11.jar commons-logging-1.1.1.jar sprin

Spring AOP AspectJ 之間的差別

面向方面的程式設計(AOP) 是一種程式設計正規化,旨在通過允許橫切關注點的分離,提高模組化。AOP提供方面來將跨越物件關注點模組化。雖然現在可以獲得許多AOP框架,但在這裡我們要區分的只有兩個流行的框架:Spring AOP和AspectJ。這裡將會幫助你基於一些關鍵資訊