AOP

觀念


AOP(Aspect Orient Programming),主要以proxy pattern將商業邏輯與業務邏輯分開,讓開發者更聚焦商業邏輯。圖中藍鍵頭為商業邏輯,紫鍵頭的為業務邏輯。在程式寫作中,經常兩者共存:

public void doAction(User user) {
    // 確認登入、權限
    if(!isLogin(user)) {
        throw new Exception();
    }
    if(!isPermitted(user) {
        throw new Exception();
    }
    // 最後才做商業邏輯
    doAction();
}

一個功能裡,經常會確認權限後才做商業邏輯。除了確認權限以外,也許還需要記錄log, ...等等。業務邏輯會橫向穿叉影響商業邏輯的進行(就像圖中那樣),Spring稱之為cross-cutting。如果每個地方都需做重複的業務邏輯,一般建議使用proxy pattern將兩者分離。但proxy用多了,也不易管理,AOP正是解決此問題。

設定

xml

<?xml version="1.0" encoding="UTF-8"?>    
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <aop:aspectj-autoproxy />
</beans>
</xml>

請特別注意以下是否有加入:

  • xmlns:aop="http://www.springframework.org/schema/aop
  • http://www.springframework.org/schema/aop
  • http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
  • <aop:aspectj-autoproxy />

Java

@Aspect
@Component
public class LoggerAop {
    // 指定切入點的package
    @Pointcut("execution(public * my.dao..*(..))")
    public void pointcut(){}

    @Before(value = "pointcut()")
    public void before(JoinPoint point) {
        String className = point.getTarget().getClass().getSimpleName();
        String methodName = point.getSignature().getName();
        System.out.println("正在調用 " + className + " - " + methodName + " 方法");
    }

    @AfterReturning(value = "pointcut()", returning = "result")
    public void afterReturn(JoinPoint point, Object result) {
        if (result != null) {
            System.out.println("結果:" + result.toString());
        } else {
            System.out.println("結果:null");
        }
    }

    // 例外通知,目標方法出現exception時執行,可以指定在出現特定例外時才執行
    // 如果把參數設成NullPointException則只在出現此例外時才執行
    @AfterThrowing(value = "pointcut()", throwing = "e")
    public void afterThrow(JoinPoint point, Exception e) {
        // ...
    }
}

說明

  • @Pointcut指定橫切點,通常值為package或某一個class。本例為my.dao下的所有class
  • @Before, @AfterReturning分別為執行業務邏輯前後的callback

使用方式

無需特別調用,只需宣告上述的@Aspect及@Pointcut就可以。

results matching ""

    No results matching ""