利用 spring aop 的 around 來實現日誌攔截器,此攔截器負責打印拋出到頂層的異常日誌。java
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.9</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.9</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2</version> </dependency>
攔截異常打印日誌,注意用線程本地變量startLocal,來作一個是否爲第一個(入口)本地方法的標誌。這樣作的目的是爲了不重複在每一個方法裏catch異常, 拋出異常操做的時候打印異常。注意catch的是 java.lang.Throwable級別的異常。包括全部的errors 和 exceptions。spring
public class LogInterceptor { private final Logger logger = LoggerFactory.getLogger(LogInterceptor.class); /** * 首次進入標誌 */ private static final ThreadLocal<Boolean> startLocal = new ThreadLocal<Boolean>(); public Object doLog(ProceedingJoinPoint jp) throws Throwable { Boolean isStart = startLocal.get(); // 作源頭標記 if (isStart == null) { startLocal.set(true); if (logger.isDebugEnabled()) { LogUtils.debug(logger, "----------開始進入全局日誌記錄攔截器-------------"); } } try { // 執行目標方法 return jp.proceed(); } catch (Throwable e) { if (isStart == null) { logger.warn("業務執行出現未知異常:", e); } throw e; } finally { if (isStart == null) { startLocal.remove(); } } } }
配置攔截器,配置切面做用的範圍的表達式express
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy proxy-target-class="true"/> <bean id="log_Interceptor" class="com.iplatform.common.interceptor.LogInterceptor"/> <aop:config> <aop:aspect order="5" id="log_interceptor_aspect" ref="log_Interceptor"> <aop:pointcut id="log_interceptor_pointcut" expression="execution(* com.tem.*.service..*.*(..)) || execution(* com.tem..*.action.*.*(..)) || execution(* com.tem..*.*Controller.*(..))"/> <aop:around method="doLog" pointcut-ref="log_interceptor_pointcut"/> </aop:aspect> </aop:config> </beans>
AOP(Aspect Oriented Programming)既面向切面編程。解決面向對象編程(OOP)所缺少的橫向邏輯處理的部分。例如每一個方法都須要的對日誌的支持,對事物的處理,對異常的處理等。這種散落在各處的重複邏輯的代碼被稱爲橫切(cross cutting)。AOP剖解開封裝的對象內部,並將那些影響了多個類的公共行爲封裝到一個可重用的模塊,並將其命名爲切面(Aspect)。編程
核心概念spa
橫切關注點線程
對那些方法繼續攔截,攔截後怎麼處理,這些關注點稱之爲橫切關注點debug
切面(aspect)代理
類是對物理特徵的抽象,切面就是對橫切關注點的抽象日誌
鏈接點(joinpoint)code
被攔截到的點,由於Spring只支持方法類型的鏈接點,因此在Spring中鏈接點指的就是被攔截到的方法,實際上鍊接點還能夠是字段或者構造器
切入點(pointcut)
對鏈接點進行攔截的定義,支持execution 表達式
通知(advice)
所謂通知指的就是指攔截到鏈接點以後要執行的代碼,通知分爲 前置、後置、異常、最終、環繞 通知五類
目標對象
代理的目標對象
織入(weave)
將切面應用到目標對象並致使代理對象建立的過程
引入(introduction)
在不修改代碼的前提下,引入能夠在運行期爲類動態地添加一些方法或字段