Spring核心思想之一是AOP(Aspect Oriented Programming),即面向切面編程的技術。 AOP讓開發人員專一核心業務,而通用邏輯則由專人使用 AOP 技術進行橫向切入處理,使得任務分離,提升開發和調試的效率,應用於權限管理、日誌管理等。html
假設項目已完成Spring、SpringMVC配置,添加AOP應用java
1.applicationContext.xml開啓支持AspectJ註解 spring
<?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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 自動掃描與裝配bean --> <context:component-scan base-package="com.product"></context:component-scan> <!-- 啓動對@AspectJ註解的支持 --> <aop:aspectj-autoproxy/> <aop:aspectj-autoproxy proxy-target-class="true" /> </beans>
2.編寫日誌切面實現apache
2.1 定義日誌註解類編程
@Inherited @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface AppLog { String value() default ""; }
2.2 日誌功能瀏覽器
package com.product.aop; import java.util.Arrays; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * 日誌demo * * */ @Component @Aspect public class LogAspect { private static final Log logger = LogFactory.getLog(LogAspect.class); //抽取公共的切入點表達式 @Pointcut("@annotation(com.product.aop.AppLog)") public void pointCut() { }; //在目標方法以前切入 @Before("pointCut()") public void logStart(JoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); System.out.println("" + joinPoint.getSignature().getName() + "運行之前:參數列表是:{" + Arrays.asList(args) + "}"); } @After("com.product.aop.LogAspect.pointCut()") public void logEnd(JoinPoint joinPoint) { System.out.println("" + joinPoint.getSignature().getName() + "運行結束。"); } // JoinPoint在參數表的第一位 @AfterReturning(value = "pointCut()", returning = "result") public void logReturn(JoinPoint joinPoint, Object result) { System.out.println("" + joinPoint.getSignature().getName() + "返回運行結果:{" + result + "}"); } @AfterThrowing(value = "pointCut()", throwing = "exception") public void logException(JoinPoint joinPoint, Exception exception) { System.out.println("" + joinPoint.getSignature().getName() + "異常,信息:{" + exception + "}"); } }
3.業務功能引入切面app
import org.springframework.stereotype.Service; import com.product.aop.AppLog; @Service("userService") public class UserService { /** * 標記日誌註解 */ @AppLog public boolean exists(String userid,String name){ System.out.println("getUser"); return true; } }
4.測試測試
瀏覽器請求http://127.0.0.1:8080/aop/user/submit.do?userid=001&name=lilei調試
控制檯輸出結果:日誌
exists運行之前:參數列表是:{[001, lilei]} getUser exists運行結束。 exists返回運行結果:{true}