成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Spring之面向切面

Olivia / 2127人閱讀

摘要:面向切面的面向切面編程的基本原理通過(guò)創(chuàng)建切面使用注解為切面注入依賴定義術(shù)語(yǔ)通知前置通知在目標(biāo)方法被調(diào)用之前調(diào)用通知功能后置通知在目標(biāo)方法完成之后調(diào)用通知,此時(shí)不會(huì)關(guān)心方法的輸出是什么返回通知在目標(biāo)方法成功執(zhí)行之后調(diào)用通知異常通知在目標(biāo)方

面向切面的Spring

面向切面編程的基本原理

通過(guò)POJO創(chuàng)建切面

使用@AspectJ注解

為AspectJ切面注入依賴

定義AOP術(shù)語(yǔ)

通知(Advice)

前置通知(Before):在目標(biāo)方法被調(diào)用之前調(diào)用通知功能

后置通知(After):在目標(biāo)方法完成之后調(diào)用通知,此時(shí)不會(huì)關(guān)心方法的輸出是什么

返回通知(After-returning):在目標(biāo)方法成功執(zhí)行之后調(diào)用通知

異常通知(After-throwing):在目標(biāo)方法拋出異常后調(diào)用通知

環(huán)繞通知(Around):通知包裹了被通知的方法,在被通知的方法調(diào)用之前和調(diào)用之后執(zhí)行自定義的行為

連接點(diǎn)(Join point),是在應(yīng)用執(zhí)行過(guò)程中能夠插入切面的一個(gè)點(diǎn)

切點(diǎn)(Poincut),利用正則表達(dá)式定義所匹配的類和方法名稱來(lái)指定切點(diǎn)

切面(Aspect),通知和切點(diǎn)的結(jié)合,它是什么,在何時(shí)何處完成其功能

引入(Introduction):允許向現(xiàn)有的類添加新方法或?qū)傩?,不影響現(xiàn)有的類

織入(Weaving):

把切面應(yīng)用到目標(biāo)對(duì)象并創(chuàng)建新的代理對(duì)象的過(guò)程

在指定的連接點(diǎn)被織入到目標(biāo)對(duì)象中

在目標(biāo)對(duì)象的生命周期里有多個(gè)點(diǎn)可以進(jìn)行織入:

編譯期:切面在目標(biāo)類編譯時(shí)被織入,如AspectJ

類加載期:切面在目標(biāo)類加載到JVM時(shí)被織入,如AspectJ 5的加載時(shí)織入(load-time weaving,LTW)

運(yùn)行期:切面在應(yīng)用運(yùn)行的某個(gè)時(shí)刻被織入,如Spring AOP

Spring對(duì)AOP的支持

基于代理的經(jīng)典Spring AOP

純POJO切面

@AspectJ注解驅(qū)動(dòng)的切面

注入式AspectJ切面(適用于Spring各版本)

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;

/**
 * 是一個(gè)切面,沒(méi)有提供前置、后置或環(huán)繞通知,而是使用了@DeclareParents注解
 * @DeclareParents注解詳解:
 * value屬性指定了哪種類型的bean要引入的接口,"+"表示Performance的所有子類型
 * defaultImpl屬性指定了引入功能提供實(shí)現(xiàn)的類
 * @DeclareParents注解所標(biāo)注的靜態(tài)屬性指明了要引入了接口
 * 
 * 在Spring應(yīng)用中把EncoreableIntroducer聲明為一個(gè)bean,當(dāng)Spring發(fā)現(xiàn)@Aspect注解時(shí)會(huì)創(chuàng)建一個(gè)代理,然后將調(diào)用委托給被代理的bean或被引入的實(shí)現(xiàn)
 * 
 */
@Aspect
public class EncoreableIntroducer {

    @DeclareParents(value="com.leaf.u_spring.chapter04.Performance+",
            defaultImpl=DefaultEncoreable.class)
    public static Encoreable encoreable;
    
    
    
}
通過(guò)切點(diǎn)來(lái)選擇連接點(diǎn)

AspectJ的切點(diǎn)表達(dá)式語(yǔ)言

AspectJ指示器和描述

arg(),限制連接點(diǎn)匹配參數(shù)為指定類型的執(zhí)行方法

@args(),限制連接點(diǎn)匹配參數(shù)由指定注解標(biāo)注的執(zhí)行方法

execution(),用于匹配是連接點(diǎn)的執(zhí)行方法

this(),限制連接點(diǎn)匹配AOP代理的bean引用為指定類型的類

target(),限制連接點(diǎn)匹配目標(biāo)對(duì)象為指定類型的類

@target(),限制連接點(diǎn)匹配特定的執(zhí)行對(duì)象,這些對(duì)象對(duì)應(yīng)的類要具有指定類型的注解

within(),限制連接點(diǎn)匹配指定的類型

@within(),限制連接點(diǎn)匹配指定注解所標(biāo)注的類型(當(dāng)使用Sping AOP時(shí),方法定義在由指定的注解所標(biāo)注的類里)

@annotation,限定匹配帶有指定注解的連接點(diǎn)

編寫切點(diǎn) Performance

import java.util.Map;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

import com.google.common.collect.Maps;

/**
 * 使用參數(shù)化的通知來(lái)記錄磁道播放的次數(shù)
 */
@Aspect
public class TrackCounter {

    private Map trackCounters = Maps.newHashMap();
    
    /**
     * 通知playTrack()方法
     * 
     * 
     * playTrack(int)指定int類型參數(shù)
     * && args(trackNumber)指定參數(shù)
     * 
     * 
     * @param trackNumber
     */
    @Pointcut("execution(* com.leaf.u_spring.chapter02.CompactDisc.playTrack(int)) && args(trackNumber)")
    public void trackPlayed(int trackNumber){}
    
    /**
     * 播放前為磁道計(jì)數(shù)
     * @param trackNumber
     */
    @Before("trackPlayed(trackNumber)")
    public void countTrack(int trackNumber){
        int currentCount = getPlayCount(trackNumber);
        trackCounters.put(trackNumber, currentCount + 1);
    }

    public int getPlayCount(int trackNumber) {
        return trackCounters.containsKey(trackNumber)?trackCounters.get(trackNumber):0;
    }
    
}

import java.util.List;

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

import com.google.common.collect.Lists;
import com.leaf.u_spring.chapter02.CompactDisc;
import com.leaf.u_spring.chapter03.BlankDisc;


/**
 * 將BlankDisc和TrackCounter定義為bean,并啟用AspectJ自動(dòng)代理
 *
 */
@Configuration
@EnableAspectJAutoProxy
public class TrackCounterConfig {

    @Bean
    public CompactDisc sgtPeppers(){
        BlankDisc cd = new BlankDisc();
        cd.setTitle("陽(yáng)光總在風(fēng)雨后");
        cd.setArtist("許美靜");
        
        List tracks = Lists.newArrayList();
        tracks.add("陽(yáng)光總在風(fēng)雨后");
        tracks.add("成都");
        tracks.add("一生所愛(ài)");
        tracks.add("我的中國(guó)心");
        tracks.add("Alone Yet Not Alone");
        cd.setTracks(tracks);
        
        return cd;
    }
    
    @Bean
    public TrackCounter trackCounter(){
        return new TrackCounter();
    }
    
}
使用注解創(chuàng)建切面

Spring使用AspectJ注解來(lái)聲明通知方法

@After 通知方法會(huì)在目標(biāo)方法返回或拋出異常后調(diào)用

@AfterReturning 通知方法會(huì)在目標(biāo)方法返回后調(diào)用

@AfterThrowing 通知方法會(huì)在目標(biāo)方法拋出異常后調(diào)用

@Around 通知方法會(huì)將目標(biāo)方法封裝起來(lái)

@Before 通知方法會(huì)在目標(biāo)方法調(diào)用之前執(zhí)行

環(huán)繞通知是最為強(qiáng)大的通知類型

Java不是動(dòng)態(tài)語(yǔ)言,編譯之后很難再添加新的功能,但是引入AOP,切面可以為Spring bean添加新方法,例EncoreableIntroducer

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * 演出效果 
 * 
 * @Aspect注解表明Audience類不僅僅是個(gè)POJO,還是一個(gè)切面
 * Audience類中的方法都使用注解來(lái)定義切面的具體行為
 */
@Aspect
public class Audience {

    /**
     * 表演之前
     */
    @Before("execution(** com.leaf.u_spring.chapter04.Performance.perform(..))")
    public void silenceCellPhones(){
        System.out.println("silence Cell Phones");
    }
    
    /**
     * 表演之前
     */
    @Before("execution(** com.leaf.u_spring.chapter04.Performance.perform(..))")
    public void takeSeates(){
        System.out.println("taking seates");
    }
    
    
    /**
     * 表演之后
     */
    @AfterReturning("execution(** com.leaf.u_spring.chapter04.Performance.perform(..))")
    public void applause(){
        System.out.println("CLAP CLAP CLAP!!!");
    }
    
    /**
     * 表演失敗之后
     */
    @AfterThrowing("execution(** com.leaf.u_spring.chapter04.Performance.perform(..))")
    public void demandRefund(){
        System.out.println("Demanding a refund");
    }
    
}

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * 演出效果 
 * 相同的切點(diǎn)表達(dá)式重復(fù)了4遍
 * @Ponitcut注解能夠在一個(gè)@AspectJ切面內(nèi)定義可重用的切點(diǎn)
 * 
 */
@Aspect
public class Audience2 {

    /**
     * 定義命名的切點(diǎn)
     */
    @Pointcut("execution(** com.leaf.u_spring.chapter04.Performance.perform(..))")
    public void performance(){}
    
    /**
     * 表演之前
     */
    @Before("performance())")
    public void silenceCellPhones(){
        System.out.println("silence Cell Phones");
    }
    
    /**
     * 表演之前
     */
    @Before("performance())")
    public void takeSeates(){
        System.out.println("taking seates");
    }
    
    
    /**
     * 表演之后
     */
    @AfterReturning("performance())")
    public void applause(){
        System.out.println("CLAP CLAP CLAP!!!");
    }
    
    /**
     * 表演失敗之后
     */
    @AfterThrowing("performance())")
    public void demandRefund(){
        System.out.println("Demanding a refund");
    }
    
}
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

/**
 * 演出效果 
 * 創(chuàng)建環(huán)繞通知
 * 
 */
@Aspect
public class Audience3 {

    /**
     * 定義命名的切點(diǎn)
     */
    @Pointcut("execution(** com.leaf.u_spring.chapter04.Performance.perform(..))")
    public void performance(){}
    
    /**
     * 環(huán)繞通知方法
     */
    @Around("performance())")
    public void watchPerformance(ProceedingJoinPoint jp){
        try {
            System.out.println("silence Cell Phones");
            System.out.println("taking seates");
            //不調(diào)用proceed方法,通知會(huì)阻塞對(duì)被通知方法的調(diào)用
            jp.proceed();
            System.out.println("CLAP CLAP CLAP!!!");
        } catch (Throwable e) {
            System.out.println("Demanding a refund");
        }
    }
    
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy            //啟用AspectJ自動(dòng)代理    XMl-->   
@ComponentScan
public class ConcertConfig {

    /**
     * 聲明Audience bean
     * @return
     */
    @Bean
    public Audience audience(){
        return new Audience();
    }
}
在XML中聲明注解

原則:基于注解的配置優(yōu)于基于Java的配置,基于Java的配置要優(yōu)于基于XML的配置

需要聲明切面,又不能為通知類添加注解時(shí),須轉(zhuǎn)向XML的配置

Spring的AOP配置能夠以非侵入式的方式聲明切面:

:定義AOP通知器

:定義AOP后置通知(不管被通知的方法是否執(zhí)行成功)

:定義AOP返回通知

:定義AOP異常通知

:定義AOP環(huán)繞通知

:定義一個(gè)切面

:?jiǎn)⒂聾AspectJ注解驅(qū)動(dòng)的切面

:定義一個(gè)AOP前置通知

:頂層的AOP配置元素,大多數(shù)的元素必須包含在元素內(nèi)

:以透明的方式為被通知的對(duì)象引入額外的接口

:定義一個(gè)切點(diǎn)

引用:《Spring In Action 4》第4章

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71165.html

相關(guān)文章

  • Spring框架我見(jiàn)(三)——IOC、AOP

    摘要:模塊負(fù)責(zé)的所有面向切面的功能??偨Y(jié)的統(tǒng)一管理,降低了對(duì)象之間的耦合對(duì)主流的框架提供了很好的集成支持提供眾多組件,事務(wù)管理,等具有高度可開(kāi)放性,開(kāi)發(fā)者可以自由選擇部分或全部主要使用工廠模式和代理模式。 聊完了Spring框架中最重要的兩種設(shè)計(jì)模式,我們來(lái)看一下Spring框架的模塊和結(jié)構(gòu)圖。 Spring框架的結(jié)構(gòu) 下圖是Spring官方給出的Spring框架的結(jié)構(gòu)圖。 showImg(...

    khs1994 評(píng)論0 收藏0
  • Spring理論基礎(chǔ)-面向切面編程

    摘要:序是的縮寫,中文翻譯是面向切面編程。首先面向切面編程這個(gè)名稱很容易讓人想起面向?qū)ο缶幊虂?lái)。這種動(dòng)態(tài)地將代碼織入到類的指定方法指定位置上的編程思想就是面向切面編程。概念面向切面編程具體的一些概念。 序 AOP是Aspect-Oriented Programming的縮寫,中文翻譯是面向切面編程。作為Spring的特征之一,是要好好學(xué)習(xí)的。 首先面向切面編程這個(gè)名稱很容易讓人想起面向?qū)ο缶?..

    voyagelab 評(píng)論0 收藏0
  • 慕課網(wǎng)_《Spring入門篇》學(xué)習(xí)總結(jié)

    摘要:入門篇學(xué)習(xí)總結(jié)時(shí)間年月日星期三說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。主要的功能是日志記錄,性能統(tǒng)計(jì),安全控制,事務(wù)處理,異常處理等等。 《Spring入門篇》學(xué)習(xí)總結(jié) 時(shí)間:2017年1月18日星期三說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:https://github.com/zccodere/s...個(gè)人學(xué)習(xí)源碼:https://git...

    Ververica 評(píng)論0 收藏0
  • Spring核心 面向切面 AOP

    摘要:下圖展示了這些概念的關(guān)聯(lián)方式通知切面的工作被稱為通知。切面在指定的連接點(diǎn)被織入到目標(biāo)對(duì)象中。該注解表明不僅僅是一個(gè),還是一個(gè)切面。 在軟件開(kāi)發(fā)中,散布于應(yīng)用中多處的功能被稱為橫切關(guān)注點(diǎn)(crosscutting concern)。通常來(lái)講,這些橫切關(guān)注點(diǎn)從概念上是與應(yīng)用的業(yè)務(wù)邏輯相分離的(但是往往會(huì)直接嵌入到應(yīng)用的業(yè)務(wù)邏輯之中)。把這些橫切關(guān)注點(diǎn)與業(yè)務(wù)邏輯相分離正是面向切面編程(AOP...

    Winer 評(píng)論0 收藏0
  • Spring旅第七站:面向切面編程(AOP)

    摘要:面向切面的本章主要內(nèi)容面向切面編程的基本原理通過(guò)創(chuàng)建切面使用注解為切面注入依賴。什么是面向切面編程切面能夠幫我們模塊化橫切關(guān)注點(diǎn)。在使用面向切面編程時(shí),我們?nèi)匀辉谝粋€(gè)地方定義通知功能,而無(wú)需修改受影響的類。切面切面是通知和切點(diǎn)的結(jié)合。 面向切面的Spring 本章主要內(nèi)容: 面向切面編程的基本原理 通過(guò)POJO創(chuàng)建切面 使用@Aspect注解 為AspectJ切面注入依賴。 說(shuō)明 ...

    趙連江 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

Olivia

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<