1. 程式人生 > >Spring-AOP @AspectJ進階之繫結連線點方法入參

Spring-AOP @AspectJ進階之繫結連線點方法入參

概述

我們前面的博文在講解切點函式時說過args()、this()、target()、@args()、@within()、@target()和@annotation()這7個函式除了可以指定類名外,還可以指定引數名將目標物件連線點上的方法入參繫結到增強的方法中

其中args()用於繫結連線點方法的入參,@annotation()用於繫結連線點方法的註解物件,而@args()用於繫結連線點方法入參的註解

例項

來看一個args()繫結引數的例項

這裡寫圖片描述

業務類

package com.xgj.aop.spring.advisor.aspectJAdvance.bindJointParameter;

import
org.springframework.stereotype.Component; /** * * * @ClassName: LogicBindService * * @Description: @Component標註的Bean * * @author: Mr.Yang * * @date: 2017年9月12日 上午1:39:23 */ @Component public class LogicBindService { public void dealLogic(String bussiness, int number) { System.out.println("deal Logic:"
+ bussiness + ", number:" + number); } }

編寫切面

package com.xgj.aop.spring.advisor.aspectJAdvance.bindJointParameter;

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

/**
 * 
 * 
 * @ClassName: BindJointPointParameterAspect
 * 
 * @Description: @Aspect標註的切面
 * 
 * @author
: Mr.Yang * * @date: 2017年9月12日 上午1:10:40 */
@Aspect public class BindJointPointParameterAspect { // ①繫結連線點引數,首先args(name,number,..)根據②處的增強方法入參找到name和number對應的型別,以得到真實的切點表示式: // target(com.xgj.aop.spring.advisor.aspectJAdvance.bindJointParameter.LogicBindService) // && args(String,int,..) // 在該增強方法織入到目標連線點時,增強方法可以通過num和name訪問到連線點方法的入參。 @Before("target(com.xgj.aop.spring.advisor.aspectJAdvance.bindJointParameter.LogicBindService) && args(name,number,..)") public void crossCodeCutting(int number, String name) throws Throwable { // ②增強方法接受連線點的引數 System.out.println("----bindJoinPointParams()----"); System.out.println("name:" + name); System.out.println("number:" + number); System.out.println("----bindJoinPointParams()----"); } }

在①處,我們通過args(name,number,..)進行連線點引數的繫結,和前面我們所講述的方式不一樣,當args()函式入參為引數名時,共包括兩方面的資訊:

  • 連線點匹配規則資訊:連線點方法第一個入參是String型別,第二個入參是int型別;

  • 連線點方法入參和增強方法入參的繫結資訊:連線點方法的第一個入參繫結到增強方法的name引數上,第二個入參繫結到增強方法的number入參上。

切點匹配和引數繫結的過程是這樣的:

  • 首先args()根據引數名稱在增強方法中查到名稱相同的入參並獲知對應的型別,這樣就知道匹配連線點方法的入參型別。

  • 其次連線點方法入參型別所在的位置則由引數名在args()函式中宣告的位置決定。

args(name,number)只匹配第一個入參是String第二個入參是int的目標類方法,如LogicBindService.dealLogic(String bussiness, int number)而不匹配LogicBindService.dealLogic( int number,String bussiness)

切點匹配和引數繫結過程:

這裡寫圖片描述

和args()一樣,其它可以繫結連線點引數的切點函式(如@args()和target()等),當指定引數名時,就同時具有匹配切點和繫結引數的雙重功能

將業務Bean和切面配置到配置檔案中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    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">

<!-- (1)宣告Context名稱空間以及Schema檔案   (2)掃描類包以及應用註解定義的bean -->
<context:component-scan base-package="com.xgj.aop.spring.advisor.aspectJAdvance.bindJointParameter"/>

<!-- 基於@AspectJ切面的驅動器 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>

<!-- 使用了@AspectJ註解的切面類 -->
<bean class="com.xgj.aop.spring.advisor.aspectJAdvance.bindJointParameter.BindJointPointParameterAspect"/>

</beans>

測試類

package com.xgj.aop.spring.advisor.aspectJAdvance.bindJointParameter;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BindJointPointParameterAspectTest {

    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/aop/spring/advisor/aspectJAdvance/bindJointParameter/conf-joinPoint.xml");

        LogicBindService logicBindService = ctx.getBean("logicBindService",
                LogicBindService.class);

        logicBindService.dealLogic("PROGRAMMING", 5);

    }
}

執行結果

2017-09-12 02:05:35,991  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@24177697: startup date [Tue Sep 12 02:05:35 BOT 2017]; root of context hierarchy
2017-09-12 02:05:36,098  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJAdvance/bindJointParameter/conf-joinPoint.xml]
----bindJoinPointParams()----
name:PROGRAMMING
number:5
----bindJoinPointParams()----
deal LogicPROGRAMMING, number:5

可見,增強方法按預期綁定了LogicBindService.dealLogic(String bussiness, int number)方法的執行期入參。
提示 為了保證例項能成功執行,必須啟用CGLib動態代理:,因為該例項需要對NaiveWaiter類進行代理(因為NaiveWaiter#simle()方法不是Waiter介面的方法),所以必須使用CGLib生成子類的代理方法。

提示 :為了保證例項能成功執行,必須啟用CGLib動態代理:<aop:aspectj-autoproxy proxy-target-class="true" />,因為該例項不涉及到介面,所以必須使用CGLib生成子類的代理方法。 當然了,即使不設定(預設為jdk反向代理),當涉及的業務類沒有介面時,spring會自動使用cglib代理