springboot~使用自定義(yi)的aspect
對某個類型中的方法進行攔截,然后加入固定的業務邏輯,這是AOP面向切面編程可以做的事,在springboot里實現aop的方法也有很多,spring-boot-starter-aop或者aspectjweaver都(dou)是可以實(shi)現(xian)的,不(bu)過(guo)我們在(zai)實(shi)現(xian)之前,先來看一(yi)下(xia)aop里(li)的幾個概(gai)念。
概念
-
切(qie)面(Aspect):是指橫切(qie)多個對象的(de)關注(zhu)點的(de)一個模塊(kuai)化,事(shi)務管(guan)理就是J2EE應用(yong)(yong)中橫切(qie)關注(zhu)點的(de)很好示例。在Spring AOP中,切(qie)面通過(guo)常規(gui)類(基(ji)本(ben)模式方法)或者通過(guo)使(shi)用(yong)(yong)了注(zhu)解@Aspect的(de)常規(gui)類來實現。
-
連接(jie)點(dian)(Joint point):是(shi)(shi)指在(zai)程序(xu)執行期間的(de)(de)一個(ge)(ge)點(dian),比(bi)如某個(ge)(ge)方法(fa)的(de)(de)執行或者是(shi)(shi)某個(ge)(ge)異常的(de)(de)處理(li)。在(zai)Spring AOP中,一個(ge)(ge)連接(jie)點(dian)往往代表(biao)的(de)(de)是(shi)(shi)一個(ge)(ge)方法(fa)執行。
-
通知(zhi)(Advice):是指(zhi)切面在某個(ge)特殊連接(jie)點上執行的動作。通知(zhi)有(you)不同(tong)類(lei)型,包(bao)括"around","before"和"after"通知(zhi)。許多AOP框架包(bao)括Spring,將通知(zhi)建(jian)模成一(yi)個(ge)攔(lan)截(jie)器,并且圍繞連接(jie)點維持一(yi)個(ge)攔(lan)截(jie)器鏈(lian)。
-
切(qie)(qie)入(ru)點(dian)(Pointcut):是(shi)指匹(pi)(pi)配(pei)連(lian)接(jie)點(dian)的(de)一個斷言。通知是(shi)和一個切(qie)(qie)入(ru)點(dian)表達式(shi)(shi)關聯的(de),并且(qie)在(zai)任何被切(qie)(qie)入(ru)點(dian)匹(pi)(pi)配(pei)的(de)連(lian)接(jie)點(dian)上運行(舉例,使(shi)用(yong)特定的(de)名字(zi)執行某個方法)。AOP的(de)核(he)心就是(shi)切(qie)(qie)入(ru)點(dian)表達式(shi)(shi)匹(pi)(pi)配(pei)連(lian)接(jie)點(dian)的(de)思想。Spring默認使(shi)用(yong)AspectJ切(qie)(qie)入(ru)點(dian)表達式(shi)(shi)語
-
引(yin)入(ru)(Introduction):代表(biao)了對一個類型(xing)額外的方(fang)法或者屬性的聲明。Spring AOP允(yun)許引(yin)入(ru)新接口到任何(he)被通(tong)知(zhi)對象(以及一個對應(ying)實現(xian))。比如,可以使用一個引(yin)入(ru)去使一個bean實現(xian)IsModified接口,從(cong)而簡化緩存機制。(在AspectJ社區中,一個引(yin)入(ru)也(ye)稱為(wei)一個inter-type declaration類型(xing)間聲明)
-
目(mu)標對象(xiang)(Target object):是指被一(yi)個(ge)或多(duo)個(ge)切面通(tong)知的那(nei)個(ge)對象(xiang)。也指被通(tong)知對象(xiang)("advised object"),由于Spring AOP是通(tong)過運行時代理(li)事項(xiang)的,這個(ge)目(mu)標對象(xiang)往往是一(yi)個(ge)代理(li)對象(xiang)。
-
AOP 代理(li)(AOP proxy):是(shi)指通(tong)(tong)過AOP框架(jia)(jia)創建的對(dui)象,用(yong)來實(shi)現切面(mian)合約的(執行通(tong)(tong)知方法等(deng)等(deng))。在Spring框架(jia)(jia)中,一(yi)個(ge)(ge)AOP代理(li)是(shi)一(yi)個(ge)(ge)JDK動態代理(li)或者是(shi)一(yi)個(ge)(ge)CGLIB代理(li)。
-
織入(Weaving):將切面(mian)和其(qi)他(ta)應用類型或者對(dui)象(xiang)連(lian)接起(qi)來,創騙一個被通知對(dui)象(xiang)。這(zhe)些可以在編(bian)譯(yi)時(如使(shi)用AspectJ編(bian)譯(yi)器)、加載時或者運(yun)行時完成。Spring AOP,比(bi)如其(qi)他(ta)純(chun)Java AOP框(kuang)架一般是在運(yun)行時完成織入。
實現
1 引用依賴包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2 添加(jia)切面和攔截的(de)行為(wei)
@Aspect
@Component
@Slf4j
public class TestAspect {
/**
* 對TestService類下面的所有方法攔截.
*/
@Pointcut("execution(* com.lind.start.test.aop.TestService.*(..))")
public void pointcut() {
}
//前置通知
@Before("pointcut()")
public void beforeMethod(JoinPoint joinPoint) {
if (joinPoint.getArgs().length == 1 && joinPoint.getArgs()[0] instanceof User) {
User user = (User) joinPoint.getArgs()[0];
user.setUsername("aop賦值");
log.info("調用了前置通知" + user.toString());
}
}
//@After: 后置通知
@After("pointcut()")
public void afterMethod(JoinPoint joinPoint) {
log.info("調用了后置通知");
}
//@AfterRunning: 返回通知 result為返回內容
@AfterReturning(value = "pointcut()", returning = "result")
public void afterReturningMethod(JoinPoint joinPoint, Object result) {
log.info("調用了返回通知");
}
//@Around:環繞通知
@Around("pointcut()")
public Object Around(ProceedingJoinPoint pjp) throws Throwable {
log.info("around執行方法之前");
Object object = pjp.proceed();
log.info("around執行方法之后--返回值:" + object);
return object;
}
}
3 調用及結果
@SpringBootTest
@RunWith(SpringRunner.class)
public class AopTest {
@Autowired
TestService testService;
@Test
public void test() {
testService.print(new User());
}
}
