1. 程式人生 > >Spring-AOP @AspectJ進階之繫結丟擲的異常

Spring-AOP @AspectJ進階之繫結丟擲的異常

概述

和通過切點函式繫結連線點資訊不同,連線點丟擲的異常必須使用AfterThrowing註解的throwing成員進行繫結

例項

這裡寫圖片描述

業務類

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

import org.springframework.stereotype.Component;

@Component
public class BussinessException {

    public void dealBussiness(String bussinessName) {
        System.out.println("dealBussiness executed"
); // just a demo code ,in fact it's not cautious if (bussinessName != null && "bug".equals(bussinessName)) throw new IllegalArgumentException("iae Exception"); else throw new RuntimeException("re Exception"); } }

切面

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

import
org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; /** * * * @ClassName: BindReturnValueAspect * * @Description: @Aspect標註的切面, * 和通過切點函式繫結連線點資訊不同,連線點丟擲的異常必須使用AfterThrowing註解的throwing成員進行繫結 * * (1)處throwing指定的異常名和(2)處入參的異常名相同,這個異常增強只在連線點丟擲的異常instanceof * IllegalArgumentException才匹配,增強方法通過iae引數可以訪問丟擲的異常物件。 * * @author
: Mr.Yang * * @date: 2017年9月12日 下午5:47:23 */
@Aspect public class BindExceptionAspect { // (1) @AfterThrowing(value = "target(com.xgj.aop.spring.advisor.aspectJAdvance.bindException.BussinessException)", throwing = "iae") public void crossCuttingCode(IllegalArgumentException iae) {// (2) System.out.println("----bindException()----"); System.out.println("exception:" + iae.getMessage()); System.out.println("----bindException()----"); } }

(1)處throwing指定的異常名和(2)處入參的異常名相同,這個異常增強只在連線點丟擲的異常instanceof IllegalArgumentException才匹配,增強方法通過iae引數可以訪問丟擲的異常物件。

配置檔案

<?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.bindException"/>

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

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

</beans>

單元測試

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

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

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

        ctx.getBean("bussinessException", BussinessException.class)
                .dealBussiness("bug");
    }
}

輸出結果

2017-09-12 20:26:25,344  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3695de1a: startup date [Tue Sep 12 20:26:25 BOT 2017]; root of context hierarchy
2017-09-12 20:26:25,458  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJAdvance/bindException/conf-bindException.xml]
dealBussiness executed
----bindException()----
exception:iae Exception
----bindException()----

可見當sdealBussiness(“bug”)丟擲異常後,異常增強起效,處理完成後,再向外丟擲IllegalArgumentException。如果將①處的程式碼調整為dealBussiness(“bug2”)後,再執行程式碼,將只看到異常輸出的資訊,異常增強沒有任何動作,這是因為RuntimeException 不按型別匹配於 IllegalArgumentException,切點不匹配。

這裡寫圖片描述

總結

通過切點複合運算,你可以定義出各種複雜的切點,使切點表示式的能力進一步提升。

你可以直接使用切點複合運算子對切點函式進行運算,也可以通過切點名引用其它命名切點。

當對同一個連線點織入多個增強時,你必須考慮讓切面類實現Ordered介面,此外還必須合理計劃同一個切面類中增強方法的宣告順序,因為這些資訊都會影響到增強的織入順序。

在@AspectJ的切點表示式中,大多數的切點函式都可以繫結連線點方法的入參,以便增強方法訪問連線點資訊。

此外,你也可以簡單地將增強方法的第一個入參定義為JoinPoint訪問連線點的上下文。