java面向切面編程總結-面向切面的本質

面向切面的本質:定義切面類並將切面類的功能織入到目標類中;html

實現方式:將切面應用到目標對象從而建立一個新的代理對象的過程。替換;正則表達式

 

使用註解@Aspect來定義一個切面,在切面中定義切入點(@Pointcut),通知類型(@Before, @AfterReturning,@After,@AfterThrowing,@Around). spring

https://www.cnblogs.com/oumyye/p/4480196.htmlexpress

 

現將圖6-6中涉及到的一些概念解釋以下。函數

切面(Aspect):

其實就是共有功能的實現。如日誌切面、權限切面、事務切面等。在實際應用中一般是一個存放共有功能實現的普通Java類,之因此能被AOP容器識別成切面,是在配置中指定的。spa

切面:織入類.net

@Aspect代理

public class MyAspect {}日誌

 

通知(Advice):

是切面的具體實現。以目標方法爲參照點,根據放置的地方不一樣,可分爲前置通知(Before)、後置通知(AfterReturning)、異常通知(AfterThrowing)、最終通知(After)與環繞通知(Around)5種。在實際應用中一般是切面類中的一個方法,具體屬於哪類通知,一樣是在配置中指定的。code

通知:織入類的事件;

@Aspect

@Component

public class LogInterceptor {

    @Pointcut("execution(public * com.oumyye.service..*.add(..))")

    public void myMethod(){};

    

    /*@Before("execution(public void com.oumyye.dao.impl.UserDAOImpl.save(com.oumyye.model.User))")*/

    @Before("myMethod()")

    public void before() {

        System.out.println("method staet");

    } 

    @After("myMethod()")

    public void after() {

        System.out.println("method after");

    } 

    @AfterReturning("execution(public * com.oumyye.dao..*.*(..))")

    public void AfterReturning() {

        System.out.println("method AfterReturning");

    } 

    @AfterThrowing("execution(public * com.oumyye.dao..*.*(..))")

    public void AfterThrowing() {

        System.out.println("method AfterThrowing");

    } 

}

 

通知傳遞參數

在Spring AOP中,除了execution和bean指示符不能傳遞參數給通知方法,其餘指示符均可以將匹配的方法相應參數或對象自動傳遞給通知方法。獲取到匹配的方法參數後經過」argNames」屬性指定參數名。以下,須要注意的是args(指示符)、argNames的參數名與before()方法中參數名 必須保持一致即param。

@Before(value="args(param)", argNames="param") //明確指定了    

public void before(int param) {    

    System.out.println("param:" + param);    

}  

 

鏈接點(Joinpoint):

就是程序在運行過程當中可以插入切面的地點。例如,方法調用、異常拋出或字段修改等,但Spring只支持方法級的鏈接點。

鏈接點:目標類+目標函數;用於切面類在運行時獲取目標對象+函數+參量上下文信息;

@Around("execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")

    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

        System.out.println("環繞通知前....");

        Object obj= (Object) joinPoint.proceed();

        System.out.println("環繞通知後....");

        return obj;

    }

 

切入點(Pointcut):

用於定義通知應該切入到哪些鏈接點上。不一樣的通知一般須要切入到不一樣的鏈接點上,這種精準的匹配是由切入點的正則表達式來定義的。

切入點:在哪裏(什麼樣函數)織入;用於在切面中註解織入到哪些範圍的哪些函數上;

定義過濾切入點函數時,直接把execution以定義匹配表達式做爲值傳遞給通知類型的以下:

@After(value="execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")

  public void after(){

      System.out.println("最終通知....");

  } 

採用與ApectJ中使用pointcut關鍵字相似的方式定義切入點表達式以下,使用@Pointcut註解:

@Pointcut("execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")

private void myPointcut(){}

@After(value="myPointcut()")

public void afterDemo(){

    System.out.println("最終通知....");

切入點指示符

爲了方法通知應用到相應過濾的目標方法上,SpringAOP提供了匹配表達式,這些表達式也叫切入點指示符,在前面的案例中,它們已屢次出現。

通配符

在定義匹配表達式時,通配符幾乎隨處可見,如*、.. 、+ ,它們的含義以下:

  • .. :匹配方法定義中的任意數量的參數,此外還匹配類定義中的任意數量包
    //任意返回值,任意名稱,任意參數的公共方法
  • execution(public * *(..))
  • //匹配com.zejian.dao包及其子包中全部類中的全部方法
  • within(com.zejian.dao..*) 
  • + :匹配給定類的任意子類
    //DaoUserwithin(com.zejian.dao.DaoUser+) 
  • * :匹配任意數量的字符
    匹配包及其子包中全部類的全部方法
  • within(com.zejian.service..*)
  • //匹配以set開頭,參數爲int類型,任意返回值的方法
  • execution(* set*(int)) 

 

execution 用於匹配方法執行的鏈接點;

within 用於匹配指定類型內的方法執行;

 

目標對象(Target):

就是那些即將切入切面的對象,也就是那些被通知的對象。這些對象中已經只剩下乾乾淨淨的核心業務邏輯代碼了,全部的共有功能代碼等待AOP容器的切入。

目標對象:目標類

<!-- 定義目標對象 -->

    <bean id="userDaos" class="com.zejian.spring.springAop.dao.daoimp.UserDaoImp" />

 

代理對象(Proxy):

將通知應用到目標對象以後被動態建立的對象。能夠簡單地理解爲,代理對象的功能等於目標對象的核心業務邏輯功能加上共有功能。代理對象對於使用者而言是透明的,是程序運行過程當中的產物。

代理對象:目標類織入切面功能後的中間層(類)

 

織入(Weaving):

將切面應用到目標對象從而建立一個新的代理對象的過程。這個過程能夠發生在編譯期、類裝載期及運行期,固然不一樣的發生點有着不一樣的前提條件。譬如發生在編譯期的話,就要求有一個支持這種AOP實現的特殊編譯器;發生在類裝載期,就要求有一個支持AOP實現的特殊類裝載器;只有發生在運行期,則可直接經過Java語言的反射機制與動態代理機制來動態實現。

織入:織入的實現方式;

 

https://blog.csdn.net/liujiahan629629/article/details/18864211

 

 

基於XML的開發

前面分析完基於註解支持的開發是平常應用中最多見的,即便如此咱們仍是有必要了解一下基於xml形式的Spring AOP開發,這裏會以一個案例的形式對xml的開發形式進行簡要分析,定義一個切面類

copycode.gif

/**

 * Created by zejian on 2017/2/20.*/

public class MyAspectXML {

 

    public void before(){

        System.out.println("MyAspectXML====前置通知");

    }

 

    public void afterReturn(Object returnVal){

        System.out.println("後置通知-->返回值:"+returnVal);

    }

 

    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

        System.out.println("MyAspectXML=====環繞通知前");

        Object object= joinPoint.proceed();

        System.out.println("MyAspectXML=====環繞通知後");

        return object;

    }

 

    public void afterThrowing(Throwable throwable){

        System.out.println("MyAspectXML======異常通知:"+ throwable.getMessage());

    }

 

    public void after(){

        System.out.println("MyAspectXML=====最終通知..來了");

    }

copycode.gif

經過配置文件的方式聲明以下(spring-aspectj-xml.xml):

copycode.gif

<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.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

 

    <!--<context:component-scan base-package=""-->

 

    <!-- 定義目標對象 -->

    <bean name="productDao" class="com.zejian.spring.springAop.dao.daoimp.ProductDaoImpl" />

 

    <!-- 定義切面 -->

    <bean name="myAspectXML" class="com.zejian.spring.springAop.AspectJ.MyAspectXML" />

    <!-- 配置AOP 切面 -->

    <aop:config>

        <!-- 定義切點函數 -->

        <aop:pointcut id="pointcut" expression="execution(* com.zejian.spring.springAop.dao.ProductDao.add(..))" />

 

        <!-- 定義其餘切點函數 -->

        <aop:pointcut id="delPointcut" expression="execution(* com.zejian.spring.springAop.dao.ProductDao.delete(..))" />

 

        <!-- 定義通知 order 定義優先級,值越小優先級越大-->

        <aop:aspect ref="myAspectXML" order="0">

            <!-- 定義通知

            method 指定通知方法名,必須與MyAspectXML中的相同

            pointcut 指定切點函數

            -->

            <aop:before method="before" pointcut-ref="pointcut" />

 

            <!-- 後置通知  returning="returnVal" 定義返回值 必須與類中聲明的名稱同樣-->

            <aop:after-returning method="afterReturn" pointcut-ref="pointcut"  returning="returnVal" />

 

            <!-- 環繞通知 -->

            <aop:around method="around" pointcut-ref="pointcut"  />

 

            <!--異常通知 throwing="throwable" 指定異常通知錯誤信息變量,必須與類中聲明的名稱同樣-->

            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="throwable"/>

 

            <!--

                 method : 通知的方法(最終通知)

                 pointcut-ref : 通知應用到的切點方法

                -->

            <aop:after method="after" pointcut-ref="pointcut"/>

        </aop:aspect>

    </aop:config>

beans 

copycode.gif

聲明方式和定義方式在代碼中已很清晰了,瞭解一下便可,在實際開發中,會更傾向與使用註解的方式開發

 

 

https://www.cnblogs.com/junzi2099/p/8274813.html

相關文章
相關標籤/搜索