Spring - AOP - Pointcut , Advisor

原文地址:https://mkyong.com/spring/spring-aop-example-pointcut-advisor/

Spring - AOP - Advice中,一個類的所有方法都會被自動攔截。但是在大多數(shù)情況下,您可能需要一種方式來僅攔截一種或兩種方法,這就是“切入點”的目的。它允許您通過方法名稱來攔截方法。此外,“切入點”必須與“Advisor”相關聯(lián)。

在Spring AOP中,提供了三個非常技術性的術語–Advice,Pointcut,Advisor,以非正式的方式進行介紹...

  • Advice - 指示在方法執(zhí)行之前或之后要執(zhí)行的操作。
  • Pointcut - 通過方法名稱或正則表達式模式指示應攔截的方法。
  • Advisor - 將“Advice”和“Pointcut”分組為一個單元,然后將其傳遞給代理工廠對象。

文件:CustomerService.java

package com.mkyong.customer.services;

public class CustomerService
{
    private String name;
    private String url;

    public void setName(String name) {
        this.name = name;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void printName(){
        System.out.println("Customer name : " + this.name);
    }
    
    public void printURL(){
        System.out.println("Customer website : " + this.url);
    }
    
    public void printThrowException(){
        throw new IllegalArgumentException();
    }
    
}

文件:Spring-Customer.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="customerService" class="com.mkyong.customer.services.CustomerService">
        <property name="name" value="Yong Mook Kim" />
        <property name="url" value="http://www.mkyong.com" />
    </bean>

    <bean id="hijackAroundMethodBeanAdvice" class="com.mkyong.aop.HijackAroundMethod" />

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

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

        <property name="interceptorNames">
            <list>
                <value>hijackAroundMethodBeanAdvice</value>
            </list>
        </property>
    </bean>
</beans>

文件:HijackAroundMethod.java

package com.mkyong.aop;

import java.util.Arrays;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class HijackAroundMethod implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {

        System.out.println("Method name : "
                + methodInvocation.getMethod().getName());
        System.out.println("Method arguments : "
                + Arrays.toString(methodInvocation.getArguments()));

        System.out.println("HijackAroundMethod : Before method hijacked!");

        try {
            Object result = methodInvocation.proceed();
            System.out.println("HijackAroundMethod : Before after hijacked!");

            return result;

        } catch (IllegalArgumentException e) {

            System.out.println("HijackAroundMethod : Throw exception hijacked!");
            throw e;
        }
    }
}

運行:

package com.mkyong.common;

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

import com.mkyong.customer.services.CustomerService;

public class App {
    public static void main(String[] args) {
        ApplicationContext appContext = new ClassPathXmlApplicationContext(
                new String[] { "Spring-Customer.xml" });

        CustomerService cust = (CustomerService) appContext
                .getBean("customerServiceProxy");

        System.out.println("*************************");
        cust.printName();
        System.out.println("*************************");
        cust.printURL();
        System.out.println("*************************");
        try {
            cust.printThrowException();
        } catch (Exception e) {
        }
    }
}

輸出:

*************************
Method name : printName
Method arguments : []
HijackAroundMethod : Before method hijacked!
Customer name : Yong Mook Kim
HijackAroundMethod : Before after hijacked!
*************************
Method name : printURL
Method arguments : []
HijackAroundMethod : Before method hijacked!
Customer website : http://www.mkyong.com
HijackAroundMethod : Before after hijacked!
*************************
Method name : printThrowException
Method arguments : []
HijackAroundMethod : Before method hijacked!
HijackAroundMethod : Throw exception hijacked!

攔截了客戶服務類的所有方法。稍后,我們向您展示如何使用“切入點”僅攔截printName()方法。

Pointcuts示例

您可以通過以下兩種方式來匹配該方法:

  • 名稱匹配
  • 正則表達式匹配

1. Pointcuts – 名稱匹配示例

通過“pointcut”和“advisor”攔截printName()方法。
創(chuàng)建一個NameMatchMethodPointcut切入點bean,然后將要攔截的方法名稱放在“ mappedName”屬性值中。

<bean id="customerPointcut"
        class="org.springframework.aop.support.NameMatchMethodPointcut">
        <property name="mappedName" value="printName" />
</bean>

創(chuàng)建一個DefaultPointcutAdvisor bean,并將advice和pointcut關聯(lián)。

<bean id="customerAdvisor"
        class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="pointcut" ref="customerPointcut" />
        <property name="advice" ref="hijackAroundMethodBeanAdvice" />
</bean>

將代理的“interceptorNames”替換為“customerAdvisor”(原為“ hijackAroundMethodBeanAdvice”)。

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

        <property name="target" ref="customerService" />
        
        <property name="interceptorNames">
            <list>
                <value>customerAdvisor</value>
            </list>
        </property>
</bean>

完整的Bean配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="customerService" class="com.mkyong.customer.services.CustomerService">
        <property name="name" value="Yong Mook Kim" />
        <property name="url" value="http://www.mkyong.com" />
    </bean>

    <bean id="hijackAroundMethodBeanAdvice" class="com.mkyong.aop.HijackAroundMethod" />

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

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

        <property name="interceptorNames">
            <list>
                <value>customerAdvisor</value>
            </list>
        </property>
    </bean>

    <bean id="customerPointcut" 
                class="org.springframework.aop.support.NameMatchMethodPointcut">
        <property name="mappedName" value="printName" />
    </bean>

    <bean id="customerAdvisor" 
                 class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="pointcut" ref="customerPointcut" />
        <property name="advice" ref="hijackAroundMethodBeanAdvice" />
    </bean>

</beans>

再次運行,輸出

*************************
Method name : printName
Method arguments : []
HijackAroundMethod : Before method hijacked!
Customer name : Yong Mook Kim
HijackAroundMethod : Before after hijacked!
*************************
Customer website : http://www.mkyong.com
*************************

現(xiàn)在,您只攔截了printName()方法。

PointcutAdvisor

Spring附帶了PointcutAdvisor類,將advisor和pointcut聲明到不同的bean中來保存你的工作,您可以使用NameMatchMethodPointcutAdvisor將兩者組合到一個bean中。

<bean id="customerAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
  
   <property name="mappedName" value="printName" />
   <property name="advice">ref="hijackAroundMethodBeanAdvice" />
  
</bean>

2. Pointcut – 正則表達式示例

您還可以使用正則表達式切入點– RegexpMethodPointcutAdvisor來匹配方法的名稱。

<bean id="customerAdvisor"
        class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="patterns">
            <list>
                <value>.*URL.*</value>
            </list>
        </property>

        <property name="advice" ref="hijackAroundMethodBeanAdvice" />
</bean>

現(xiàn)在,它攔截了在方法名稱中帶有單詞“ URL”的方法。
實際上,您可以使用它來管理DAO層,在其中可以聲明“.* DAO.*”來攔截所有DAO類以支持事務。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容