1. 程式人生 > >spring AOP 之三:使用@AspectJ定義切入點

spring AOP 之三:使用@AspectJ定義切入點

@AspectJ相關文章

使用註解來建立切面是AspectJ 5所引入的關鍵特性。AspectJ 5之前,編寫AspectJ切面需要學 習一種Java語言的擴充套件,但是AspectJ面向註解的模型可以非常簡便地通過少量註解把任意類 轉變為切面。

AspectJ提供了五個註解來定義通知,如表4.2所示:

表4.2 Spring使用AspectJ註解來宣告通知方法

示例1:Audience類:觀看演出的切面

package com.dxz.aop.demo7;

import org.springframework.stereotype.Component;

@Component
public class Performance { public void perform(){ System.out.println("我是男一號,我正在表演"); } } package com.dxz.aop.demo7; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.context.annotation.Configuration; @Aspect @Configuration
public class Audience { /** * 手機調至靜音狀態 */ @Before("execution(** com.dxz.aop.demo7.Performance.perform(..))") public void silenceCellPhones() { System.out.println("silence cell phones"); } /** * 就坐 */ @Before("execution(** com.dxz.aop.demo7.Performance.perform(..))")
public void takeSeats() { System.out.println("taking seats"); } /** * 鼓掌喝彩 */ @AfterReturning("execution(** com.dxz.aop.demo7.Performance.perform(..))") public void applause() { System.out.println("CLAP CLAP CLAP!"); } /** * 退款 */ @AfterReturning("execution(** com.dxz.aop.demo7.Performance.perform(..))") public void demandRefund() { System.out.println("demanding a refund"); } } package com.dxz.aop.demo7; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.Import; @Configuration @ComponentScan @EnableAspectJAutoProxy @Import({Audience.class})/*@Aspect可以生效,相當於Configuration類作用,都是配置類*/ public class AppConfig { }

啟動類:

package com.dxz.aop.demo7;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test7 {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Performance outPut = (Performance) context.getBean("performance");
        outPut.perform();
    }
}

結果:

你可能已經注意到了,所有的這些註解都給定了一個切點表示式作為它的值,同時,這四個方法的切點表示式都是相同的。其實,它們可以設定成不同的切點表示式,但是在這裡,這個切點表示式就能滿足所有通知方法的需求。這樣的重複讓人感覺有些不對勁。如果我們只定義這個切點一次,然後每次需要的時候引用它,那麼這會是一個很好的方案。

幸好,我們完全可以這樣做:@Pointcut註解能夠在一個@AspectJ切面內定義可重用的切 點。接下來的程式清單4.2展現了新的Audience,現在它使用了@Pointcut。

示例2:@Pointcut註解宣告頻繁使用的切點表示式

package com.dxz.aop.demo7;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;

@Aspect
@Configuration
public class Audience2 {

    @Pointcut("execution(** com.dxz.aop.demo7.Performance.perform(..))")
    public void performance() {}
    
    /**
     * 手機調至靜音狀態
     */
    @Before("performance()")
    public void silenceCellPhones() {
        System.out.println("silence cell phones");
    }
    
    /**
     * 就坐
     */
    @Before("performance()")
    public void takeSeats() {
        System.out.println("taking seats");
    }
    
    /**
     * 鼓掌喝彩
     */
    @AfterReturning("performance()")
    public void applause() {
        System.out.println("CLAP CLAP CLAP!");
    }
    
    /**
     * 退款
     */
    @AfterReturning("performance()")
    public void demandRefund() {
        System.out.println("demanding a refund");
    }
}
package com.dxz.aop.demo7;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
@Import({Audience2.class})/*@Aspect可以生效,相當於Configuration類作用,都是配置類*/  
public class AppConfig {

}

結果和示例同等效果

環繞通知(around advice)

示例3:我們使用一個環繞通知來代替之前多個 不同的前置通知和後置通知

package com.dxz.aop.demo7;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;

@Aspect
@Configuration
public class Audience3 {

    @Pointcut("execution(** com.dxz.aop.demo7.Performance.perform(..))") //定義命名額切點
    public void performance() {
    }

    @Around("performance()") //環繞通知方法
    public void watchPerformance(ProceedingJoinPoint jp) {
        try {
            System.out.println("silence cell phones");
            System.out.println("taking seats");
            jp.proceed();
            System.out.println("CLAP CLAP CLAP!");
            System.out.println("demanding a refund");
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}
package com.dxz.aop.demo7;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
@Import({Audience3.class})/*@Aspect可以生效,相當於Configuration類作用,都是配置類*/  
public class AppConfig {

}

其它不變,執行結果同上

對於Introduction這個詞,個人認為理解成引入是最合適的,其目標是對於一個已有的類引入新的介面(有人可能會問:有什麼用呢?簡單的說,你可以把當前物件轉型成另一個物件,那麼很顯然,你就可以呼叫另一個物件的方法了),看一個例子就全明白了。  

假設已經有一個UserService類提供了儲存User物件的服務,但是現在想增加對User進行驗證的功能,只對通過驗證的User提供儲存服務,在不修改UserService類程式碼的前提下就可以通過Introduction來解決。

定義一個名為 Skill 的介面及它的實現類 SkillImpl。我們將要把 SkillImpl 的getSkill()方法新增到其他的類例項

package com.dxz.aop.demo8;

public interface Person {
    public void sayIdentification();
}
package com.dxz.aop.demo8;

import org.springframework.stereotype.Component;

@Component
public class Student implements Person {

    public void sayIdentification() {
        System.out.println("hello world!");
        
    }

}

附加的功能

package com.dxz.aop.demo8;

import org.springframework.stereotype.Component;

@Component
public interface Skill {
    void getSkill(String skill);
}

package com.dxz.aop.demo8;

import org.springframework.stereotype.Component;

@Component
public class SkillImpl implements Skill {

    public void getSkill(String skill) {
        System.out.println(skill);
    }
    
}

SpringAop 配置類

package com.dxz.aop.demo8;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class AopConfig {

    // “...demo8.Perso”後面的 “+” 號,表示只要是Person及其子類都可以新增新的方法
    @DeclareParents(value = "com.dxz.aop.demo8.Person+", defaultImpl = SkillImpl.class)
    public Skill skill;
}

SpringConfig 配置類

package com.dxz.aop.demo8;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@ComponentScan
@Configuration
@EnableAspectJAutoProxy
public class SpringConfig {
}

Test

package com.dxz.aop.demo8;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AopTest {

    @Autowired
    private Student student;

    @Test
    public void test(){
        Skill skill = (Skill)student; // 通過型別轉換,student物件就擁有了SkillImp 類的方法
        skill.getSkill("我會英語");
        student.sayIdentification();
    }
}

結果:

相關推薦

spring AOP 使用@AspectJ定義切入點

@AspectJ相關文章 使用註解來建立切面是AspectJ 5所引入的關鍵特性。AspectJ 5之前,編寫AspectJ切面需要學 習一種Java語言的擴充套件,但是AspectJ面向註解的模型可以非常簡便地通過少量註解把任意類 轉變為切面。 AspectJ提供了五個註解來定義通知,如表4

spring AOP @AspectJ切入點識別符號語法詳解

@AspectJ相關文章   Spring AOP支援的AspectJ切入點指示符(用來指示切入點表示式目的),在Spring AOP中目前只有執行方法這一個連線點(因為Spring基於動態代理,所以Spring只支援方法連線點。這與一些其他的AOP框架是不同的,例如AspectJ和JBoss,

spring AOP @AspectJ註解的3種配置

@AspectJ相關文章 與 AspectJ 相同的是,Spring AOP 同樣需要對目標類進行增強,也就是生成新的 AOP 代理類;與 AspectJ 不同的是,Spring AOP 無需使用任何特殊命令對 Java 原始碼進行編譯,它採用執行時動態地、在記憶體中臨時生成“代理類”的方式

spring security起步定義登入配置與form-login屬性詳解

在上一篇部落格spring security起步二:自定義登入頁中我們實現瞭如何自定義登入頁,但是還存在很多問題: 1.spring security如何對登入請求進行攔截 2.登入成功後如何跳轉 3.登入失敗後如何跳轉 form-login屬性詳解

彈窗定義Dialog

第一步: 給Dialog設定一個風格主題 (基本都是用這個主題)無邊框全透明背景: res/values/styles: <!--自定義dialog背景全透明無邊框theme --> <style name="MyDi

android中的對話方塊定義對話方塊

首先看下效果圖 下面講一下具體的實現: 1.修改系統預設的Dialog樣式(風格、主題) 2.自定義Dialog佈局檔案 3.可以自己封裝一個類,繼承自Dialog或者直接使用Dialog類來實現,為了方便以後重複使用,建議自己封裝一個Dialog類 ==

Spring系列SpringBean的單例構造和多例構造(Maven Idea)

在使用Spring的Ioc容器建立物件會使用到單例構造或多例構造;單例構造:整個程式只有一個物件多例構造:程式中有類例項的多個物件,物件之間互相獨立首先在Test包下面建立一個User類,原始碼如下;package com.lydetails.ssm.Test; public

定義spring boot starter三部曲原始碼分析spring.factories載入過程

本文是《自定義spring boot starter三部曲》系列的終篇,前文中我們開發了一個starter並做了驗證,發現關鍵點在於spring.factories的自動載入能力,讓應用只要依賴starter的jar包即可,今天我們來分析Spring和Spring boot原始碼,瞭解s

Spring原理學習系列Spring AOP原理(從原始碼層面分析)-------上部

引言 本文是Spring原理分析的第三篇博文,主要闡述Spring AOP相關概念,同時從原始碼層面分析AOP實現原理。對於AOP原理的理解有利於加深對Spring框架的深入理解。同時我也希望可以探究Spring框架在處理AOP的解決思路,學習框架的時候,有時候

Https系列讓服務器同時支持http、https,基於spring boot

signed 默認 gfs proc idl clas 兩種方法 .... gpg Https系列會在下面幾篇文章中分別作介紹: 一:https的簡單介紹及SSL證書的生成二:https的SSL證書在服務器端的部署,基於tomcat,spring boot三:讓服務器同時

SDS趨勢開源軟件定義存儲

sds 開源存儲 大家都知道IT圈有個非常著名的曲線圖,就是Gartner的新興技術成熟度曲線(Hype Cycle),昨天看了一下Gartner 2016的存儲成熟曲線圖,今天給大家簡單聊聊,多多指教。:) 廢話不多說,直接上圖先簡單說說這個曲線圖,成熟曲線圖將每種技術的優點與Gartner所期望其

spring boot 系列spring boot 整合JdbcTemplate

closed com context boot pin pan url wired ace 前面兩篇文章我們講了兩件事情: 通過一個簡單實例進行spring boot 入門 修改spring boot 默認的服務端口號和默認context path 這篇文章我們來看下怎

Spring(十九)Spring AOP切面的優先級

表達 對象 技術分享 方法 多個 getname exp 訪問 ioc容器 背景: 1)指定切面優先級示例:有的時候需要對一個方法指定多個切面,而這多個切面有時又需要按照不同順序執行,因此,切面執行優先級別指定功能就變得很實用。 2)重復使用切入點表達式:上一篇文章中,

Spring Aop個註解@Around,@Before,@After

如果 aop 被調用 調用 pri npoi 能說 說明 其中 最近抽時間看了一些aop。好像翻譯叫做切片技術。大概也能說明白是什麽意思。 其中,有三個註解需要註意,分別是@Around,@Before,@After。 其中 @Around進行切片捕捉,可以捕捉到joinp

Spring Boot 系統Spring Boot 整合JdbcTemplate

前面兩篇文章我們講了兩件事情: 通過一個簡單例項進行Spring Boot 入門 修改Spring Boot 預設的服務埠號和預設context path 這篇文章我們來看下怎麼通過JdbcTemplate進行資料的持久化。 一、程式碼實現 1、修改pom.xml檔案

java基礎(五)spring aop @aspect

Aspectj切入點語法定義 例如定義切入點表示式 execution(* com.sample.service.impl….(…)) 一:execution()是最常用的切點函式,其語法如下所示: pointcut 宣告"切入點", 整個表示式可以分為五個部分

Spring原始碼解析(自定義標籤的解析)

自定義標籤的解析 1、概述:通過前面的文章我們分析了預設標籤的解析,我們先回顧下自定義標籤解析所使用的方法 /** * Parse the elements at the root level in the document: * "import", "alias", "bean".

探析Spring AOPSpring AOP的底層實現原理

一、前言   前面第一篇我們講到了AOP的概念和使用,第二篇也講到了 AOP的實現機制,在第一篇,講到了joinpoint,pointcut,aspect,weave等AOP的核心概念,接下來我們詳解分析他們的實現原理!   在動態代理 和 CGLIB 的支

Spring AOPAspectJ的註解方式使用

需要匯入的jar包,請看上一篇部落格。 註解: 如果使用註解進行aop開發,必須進行aspectj自動代理 <aop:aspectj-autoproxy> 通知註解 @Before 前置 @AfterReturning 後置

10、SSM框架-Spring AOP基於註解的宣告式AspectJ(10)

spring除了支援Schema方式配置AOP,還支援註解方式:使用@AspectJ風格的切面宣告。匯入需要的包:aspectjweaver.jar、aopalliance-1.0.jar 一、基本使用方法  1.1、啟用對@AspectJ的支援        Sprin