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就可以。