import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.time.LocalDateTime; @Aspect @Component// 很是重要 @Slf4j public class LogInterceptor { // 定義默認切入點 @Pointcut("execution(* com.xxx.cloud.controller.*.*(..))") private void anyMethod() { } // 定義手動切點 @Pointcut(value = "@annotation(LogThread)") private void pointcut() { } @Around(value = "anyMethod() || pointcut()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("進入環繞通知"); ThreadInfo threadInfo = new ThreadInfo(); threadInfo.setStartTime(LocalDateTime.now()); threadInfo.setId(Thread.currentThread().getId()); threadInfo.setName(Thread.currentThread().getName()); // threadInfo.setHost(hostUtils.getHostName()); // threadInfo.setService(hostUtils.getServerName()); Object object = null; try { object = pjp.proceed(); // 執行該方法 threadInfo.setResult(0); } catch (Exception e) { threadInfo.setResult(1); log.error(e.getMessage()); } finally { threadInfo.setFinishTime(LocalDateTime.now()); ThreadUtils.threads.add(threadInfo); } System.out.println("退出環繞通知"); return object; } // ThreadInfo threadInfo; // @Before("anyMethod() && args(name)") @Before("anyMethod() || @annotation(LogThread)") public void before() { // public void doAccessCheck(String name) { // System.out.println(name); System.out.println("前置通知"); } @After("anyMethod() || pointcut()") public void after(JoinPoint point) { System.out.println("後置通知"); } @AfterReturning("anyMethod() || pointcut()") public void afgerRturning() { System.out.println("返回通知"); } @AfterThrowing("anyMethod() || pointcut()") public void afterThrowing() { System.out.println("異常通知"); } }
import java.lang.annotation.*; /** * 元註解(meta-annotation): * * 元註解的做用就是負責註解其餘註解。Java5.0定義了4個標準的meta-annotation類型,它們被用來提供對其它 annotation類型做說明。Java5.0定義的元註解: * 1.@Target, * 2.@Retention, * 3.@Documented, * 4.@Inherited */ /** * @Target說明了Annotation所修飾的對象範圍:Annotation可被用於 packages、types(類、接口、枚舉、Annotation類型)、類型成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循環變量、catch參數)。在Annotation類型的聲明中使用了target可更加明晰其修飾的目標。 * * 做用:用於描述註解的使用範圍(即:被描述的註解能夠用在什麼地方) * * 取值(ElementType)有: * * 1.CONSTRUCTOR:用於描述構造器 * 2.FIELD:用於描述域 * 3.LOCAL_VARIABLE:用於描述局部變量 * 4.METHOD:用於描述方法 * 5.PACKAGE:用於描述包 * 6.PARAMETER:用於描述參數 * 7.TYPE:用於描述類、接口(包括註解類型) 或enum聲明 */ @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE }) /** * @Retention定義了該Annotation被保留的時間長短:某些Annotation僅出如今源代碼中,而被編譯器丟棄;而另外一些卻被編譯在class文件中;編譯在class文件中的Annotation可能會被虛擬機忽略,而另外一些在class被裝載時將被讀取(請注意並不影響class的執行,由於Annotation與class在使用上是被分離的)。使用這個meta-Annotation能夠對 Annotation的「生命週期」限制。 * * 做用:表示須要在什麼級別保存該註釋信息,用於描述註解的生命週期(即:被描述的註解在什麼範圍內有效) * * 取值(RetentionPoicy)有: * * 1.SOURCE:在源文件中有效(即源文件保留) * 2.CLASS:在class文件中有效(即class保留) * 3.RUNTIME:在運行時有效(即運行時保留) * * Retention meta-annotation類型有惟一的value做爲成員,它的取值來自java.lang.annotation.RetentionPolicy的枚舉類型值。 */ @Retention(RetentionPolicy.RUNTIME) /** * @Documented用於描述其它類型的annotation應該被做爲被標註的程序成員的公共API,所以能夠被例如javadoc此類的工具文檔化。 * Documented是一個標記註解,沒有成員。 */ @Documented /** * @Inherited 元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。若是一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。 * * 注意:@Inherited annotation類型是被標註過的class的子類所繼承。類並不從它所實現的接口繼承annotation,方法並不從它所重載的方法繼承annotation。 * * 當@Inherited annotation類型標註的annotation的Retention是RetentionPolicy.RUNTIME,則反射API加強了這種繼承性。若是咱們使用java.lang.reflect去查詢一個@Inherited annotation類型的annotation時,反射代碼檢查將展開工做:檢查class和其父類,直到發現指定的annotation類型被發現,或者到達類繼承結構的頂層。 */ @Inherited public @interface LogThread { // String operateDescribe() default ""; }