SpringBoot項目使用aop案例詳解
前言
IOC和AOP是Spring中的兩個核心的概念,簡單介紹一下我的理解:
IOC:控制反轉(zhuǎn),就是將以前由我們自己手動創(chuàng)建對象的過程交給了Spring,Spring幫助我們生產(chǎn)對象、管理對象、管理對象和對象之間的依賴關(guān)系。降低了代碼的耦合度,方便我們后期對項目做維護。舉個通俗一點的例子:
正常情況下,我們在家,餓了,自己做飯。
使用IOC情況下,我們在家,餓了,打電話給商家,飯送過來。
IOC就相當(dāng)于商家,做飯就相當(dāng)于創(chuàng)建對象。
也就是說正常情況下,當(dāng)一個類需要調(diào)用其他類的方法時,我們手動通過new、工廠或者其他方式創(chuàng)建對象。
使用IOC情況下,我們只需要注入對象即可。
AOP:面向切面(方便)編程,可以對某一類對象進行監(jiān)督和控制,在調(diào)用這類對象方法的前后去調(diào)用指定的代碼,從而對一個方法進行擴展,從而達(dá)到增強模塊功能的效果。舉個通俗一點的例子:
正常情況下,直接吃飯。
使用AOP情況下,有個保姆關(guān)注著,吃飯前幫忙洗手,吃飯后幫忙收拾碗筷。
AOP就相當(dāng)于保姆,吃飯就相當(dāng)于帶調(diào)用具體的方法。
也就是說,當(dāng)我們想對方法進行補充時,并不去直接修改方法,而是通過AOP去補充。當(dāng)我們不想補充或者需要更換補充的時候,直接操作AOP即可。
1、Pointcut: 切點,用于定義哪個方法會被攔截,例如 execution(* cn.springcamp.springaop.service..(…))
2、Advice: 攔截到方法后要執(zhí)行的動作
3、Aspect: 切面,把Pointcut和Advice組合在一起形成一個切面
4、Join Point: 在執(zhí)行時Pointcut的一個實例
4、Weaver: 實現(xiàn)AOP的框架,例如 AspectJ 或 Spring AOP
一、SpringBoot項目引入AOP依賴
<!--aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>啟動類加上@EnableAspectJAutoProxy注解,可以省略。因為在AOP的默認(rèn)配置屬性中,spring.aop.auto屬性默認(rèn)是開啟的。
也不需要再引入AspectJ依賴了。
二、普通方式
切面類代碼:
package com.example.myblog.test;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AOPTest {
//定義切入點
@Pointcut("execution(public * com.example.myblog.test.AOPTestClient.*(..))")
public void aspectTest(){}
//前置通知,切入點執(zhí)行之前執(zhí)行
@Before("aspectTest()")
public void doBefore(JoinPoint joinPoint){
System.out.println("前置通知");
}
//后置通知,切入點執(zhí)行之后執(zhí)行
@After("aspectTest()")
public void doAfter(JoinPoint joinPoint){
System.out.println("后置通知");
}
//最終通知,,切入點執(zhí)行之后執(zhí)行
@AfterReturning("aspectTest()")
public void doAfterReturning(JoinPoint joinPoint){
System.out.println("最終通知");
}
//異常通知,切入點拋出異常執(zhí)行
@AfterThrowing("aspectTest()")
public void deAfterThrowing(JoinPoint joinPoint){
System.out.println("異常通知");
}
//環(huán)繞通知,切入點執(zhí)行前、后執(zhí)行
@Around("aspectTest()")
public Object deAround(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("未執(zhí)行");
Object result = joinPoint.proceed();
System.out.println("已執(zhí)行");
//返回結(jié)果
return result;
}
}
切點類代碼:
package com.example.myblog.test;
import org.springframework.stereotype.Component;
@Component
public class AOPTestClient {
public void test(){
System.out.println("正在測試AOP");
}
}測試類代碼:
package com.example.myblog;
import com.example.myblog.test.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class MyblogApplicationTests {
@Autowired
private AOPTestClient aopTestClient;
@Test
public void testAOP(){
aopTestClient.test();
}
}測試結(jié)果:

三、注解方式
自定義注解代碼:
package com.example.myblog.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//表示次注解可以標(biāo)注在類和方法上
@Target({ElementType.METHOD, ElementType.TYPE})
//運行時生效
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
//定義一個變量,可以接受參數(shù)
String desc() default " ";
}切面類代碼:
package com.example.myblog.test;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AOPAnnotationTest {
//定義切入點
@Pointcut("@annotation(com.example.myblog.test.MyAnnotation)")
public void aspectTest(){}
//前置通知,切入點執(zhí)行之前執(zhí)行
@Before("aspectTest()")
public void doBefore(JoinPoint joinPoint){
System.out.println("前置通知");
}
//后置通知,切入點執(zhí)行之后執(zhí)行
@After("aspectTest()")
public void doAfter(JoinPoint joinPoint){
System.out.println("后置通知");
}
//最終通知,,切入點執(zhí)行之后執(zhí)行
@AfterReturning("aspectTest()")
public void doAfterReturning(JoinPoint joinPoint){
System.out.println("最終通知");
}
//異常通知,切入點拋出異常執(zhí)行
@AfterThrowing("aspectTest()")
public void deAfterThrowing(JoinPoint joinPoint){
System.out.println("異常通知");
}
//環(huán)繞通知,切入點執(zhí)行前、后執(zhí)行
@Around("aspectTest()")
public Object deAround(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("未執(zhí)行");
Object result = joinPoint.proceed();
System.out.println("已執(zhí)行");
//返回結(jié)果
return result;
}
}
切點類代碼:
package com.example.myblog.test;
import org.springframework.stereotype.Component;
@Component
public class AOPAnnotationTestClient {
@MyAnnotation
public void test(){
System.out.println("正在測試AOP");
}
}測試類代碼:
@Test
public void testAOPAnnotation(){
aopAnnotationTestClient.test();
}測試結(jié)果:

到此這篇關(guān)于SpringBoot項目使用aop的文章就介紹到這了,更多相關(guān)SpringBoot使用aop內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringMVC異常全局捕獲與錯誤響應(yīng)的處理方法
編程式異常處理是通過在代碼中?顯式編寫異常捕獲邏輯(如?try-catch?塊)來管理異常的方式,開發(fā)者需要手動處理每一個可能拋出異常的代碼段,本文給大家介紹SpringMVC異常全局捕獲與錯誤響應(yīng)的處理方法,感興趣的朋友一起看看吧2025-03-03
SpringBoot采用Dynamic-Datasource方式實現(xiàn)多JDBC數(shù)據(jù)源
在某些情況下,如果我們需要配置多個數(shù)據(jù)源,本文主要介紹了SpringBoot采用Dynamic-Datasource方式實現(xiàn)多JDBC數(shù)據(jù)源,具有一定的參考價值,感興趣的可以了解一下2023-10-10
關(guān)于elcipse 安裝lombok插件解決 @Slf4j 等找不到log變量問題
這篇文章主要介紹了關(guān)于elcipse 安裝lombok插件解決 @Slf4j 等找不到log變量問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
Java中ExecutorService和ThreadPoolExecutor運行原理
本文主要介紹了Java中ExecutorService和ThreadPoolExecutor運行原理,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08
解決IDEA?JDK9沒有module-info.java的問題
這篇文章主要介紹了解決IDEA?JDK9沒有module-info.java的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
Nginx+SpringCloud Gateway搭建項目訪問環(huán)境
本文主要介紹了Nginx+SpringCloud Gateway搭建項目訪問環(huán)境,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08

