創建SpringBoot項目

添加組織名

選擇web

輸入項目名稱

創建后目錄結構為

使用Spring的AOP先加入Maven依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
這里先創建一個自己定義的注解
加入自定義注解需要的注釋

@Documented //注解表明制作javadoc時,是否將注解信息加入文檔。如果注解在聲明時使用了@Documented,則在制作javadoc時注解信息會加入javadoc。
@Target(ElementType.TYPE) //接口、類、枚舉、注解
@Target(ElementType.FIELD) //字段、枚舉的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法參數
@Target(ElementType.CONSTRUCTOR) //構造函數
@Target(ElementType.LOCAL_VARIABLE)//局部變量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包
@Retention(RetentionPolicy.SOURCE) —— 這種類型的Annotations只在源代碼級別保留,編譯時就會被忽略
@Retention(RetentionPolicy.CLASS) —— 這種類型的Annotations編譯時被保留,在class文件中存在,但JVM將會忽略
@Retention(RetentionPolicy.RUNTIME) —— 這種類型的Annotations將被JVM保留,所以他們能在運行時被JVM或其他使用反射機制的代碼所讀取和使用.
package vip.oldboy;
import java.lang.annotation.*;
/**
* Created by peng on 18/6/29.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OldBoy {
}
AOP配置

@Service用於標注業務層組件
@Controller用於標注控制層組件(如struts中的action)
@Repository用於標注數據訪問組件,即DAO組件
@Component泛指組件,當組件不好歸類的時候,我們可以使用這個注解進行標注。
@Aspect//切面
@Pointcut//定義需要切面的地方,表達式參數(https://blog.csdn.net/elim168/article/details/78150438)
@annotation//當執行的方法上擁有指定的注解時生效。
@After
@Before
@Around
就不用解釋了。
package vip.oldboy;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* Created by peng on 18/6/29.
*/
@Component
@Aspect
public class OldBoyAspect {
@Pointcut("@annotation(vip.oldboy.OldBoy)")
private void oldboy() { }
/**
* 定制一個環繞通知
* @param joinPoint
*/
@Around("oldboy()")
public void advice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Around Begin");
joinPoint.proceed();//執行到這里開始走進來的方法體(必須聲明)
System.out.println("Around End");
}
//當想獲得注解里面的屬性,可以直接注入改注解
//方法可以帶參數,可以同時設置多個方法用&&
@Before("oldboy()")
public void record(JoinPoint joinPoint) {
System.out.println("Before");
}
@After("oldboy()")
public void after() {
System.out.println("After");
}
}
ProceedingJoinPoint和JoinPoint說明
AspectJ使用org.aspectj.lang.JoinPoint接口表示目標類連接點對象,如果是環繞增強時,使用org.aspectj.lang.ProceedingJoinPoint表示連接點對象,該類是JoinPoint的子接口。任何一個增強方法都可以通過將第一個入參聲明為JoinPoint訪問到連接點上下文的信息。我們先來了解一下這兩個接口的主要方法:
1.JoinPoint
java.lang.Object[] getArgs():獲取連接點方法運行時的入參列表;
Signature getSignature() :獲取連接點的方法簽名對象;
java.lang.Object getTarget() :獲取連接點所在的目標對象;
java.lang.Object getThis() :獲取代理對象本身;
2.ProceedingJoinPoint
ProceedingJoinPoint繼承JoinPoint子接口,它新增了兩個用於執行連接點方法的方法:
java.lang.Object proceed() throws java.lang.Throwable:通過反射執行目標對象的連接點處的方法;
java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通過反射執行目標對象連接點處的方法,不過使用新的入參替換原來的入參。
控制層

package vip.oldboy;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by peng on 18/6/29.
*/
@RestController
public class OldBoyController {
@OldBoy
@RequestMapping("/oldboy")
public void getLog(){
System.out.println("oldboy is coming");
}
}
最后項目結構

啟動項目,訪問地址localhost:8080/oldboy

總結
Around最先執行
然后在執行proceed方法之前,Before先執行
然后才是方法體本身
然后是Around再結尾
最后才是After

