SpringAOP_設定注入實現
AOP_面向切面程式設計初步瞭解
讓我們先想象一個場景,你正在編寫一個專案,在開發過程中的多個模組都有某段重複的程式碼,於是你選擇將其抽象成一個方法,然後在需要的地方呼叫這個方法,當需要修改這段程式碼時只需要修改這個方法就行。有一天,你的Boss給了新的需求,需要再抽象出一個方法,然後再在各個需要這個方法的模組呼叫這個方法,這可能就讓你頭疼了,需要修改大量的程式碼,於是會想,能不能不修改原始碼為系統業務新增某種功能呢?幸運的是,AOP可以很好的解決這個問題。
簡單介紹
AOP:保證開發者不修改原始碼的前提下,去為系統中的業務元件新增某種通用功能,本質是由AOP框架修改業務元件的多個方法的原始碼,我們將其分為兩類:
- 靜態AOP
AOP 框架在編譯階段對程式原始碼進行修改,生成了靜態的 AOP 代理類(生成的*.class檔案已經被改掉了,需要使用特定的編譯器),比如 AspectJ。 - 動態AOP:
AOP 框架在執行階段對動態生成代理物件(在記憶體中以 JDK 動態代理,或 CGlib 動態地生成 AOP 代理類),如 SpringAOP。
詳細說明
Spring 的通知型別
名稱 | 標籤 | 說明 |
---|---|---|
前置通知 | < aop:before > | 用於配置前置通知。指定增強的方法在切入點方法之前執行 |
後置通知 | < aop:after-returning > | 用於配置後置通知。指定增強的方法在切入點方法之後執行 |
環繞通知 | < aop:around > | 用於配置環繞通知。指定增強的方法在切入點方法之前和之後都執行 |
異常通知 | < aop:throwing > | 用於配置異常丟擲通知。指定增強的方法在出現異常時執行 |
最終通知 | < aop:after > | 用於配置最終通知。無論增強方式執行是否有異常都會執行 |
實戰演練
匯入依賴包
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
建立一個增強類以及其介面
增強類介面:
public interface VisitService {
//用於實現前置通知,後置通知,異常通知,最終通知
void visit(String str) throws Exception;
//用於實現環繞通知
void around();
}
增強類:
public class VisitServiceImpl implements VisitService {
//前置,後置,最終,異常通知的增強類
public void visit(String str) throws Exception{
System.out.println(str);
if(!str.equalsIgnoreCase("agree")){
throw new Exception("非法訪問");
}
}
//環繞通知的增強類
public void around() {
System.out.println("環繞通知");
}
}
建立一個切面類
public class VisitAspect {
//前置通知
public void visitBefore(JoinPoint joinPoint){
System.out.println("口令:");
}
//最終通知,無論是否報錯,都執行
public void visitAfter(JoinPoint joinPoint){
System.out.println("輸入完成");
}
//後置通知報錯不執行
public void visitSuccess(JoinPoint joinPoint){
System.out.println("請求成功,歡迎");
}
//異常通知,報錯後執行
public void visitThrow(JoinPoint joinPoint, Throwable ex){
System.out.println("請求失敗,拒絕");
}
//環繞通知,如果報錯只執行前一句
public Object visitAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("-------環繞-------");
Object obj = proceedingJoinPoint.proceed();
System.out.println("-------環繞-------");
return obj;
}
}
配置xml檔案,需要新增第三方約束
<bean id="userDao" class="Spring_AOP.service.impl.VisitServiceImpl"></bean>
<bean id="aspect" class="Spring_AOP.service.VisitAspect"></bean>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* Spring_AOP.service.impl.VisitServiceImpl.visit(..))"/>
<aop:pointcut id="pointcut1" expression="execution(* Spring_AOP.service.impl.VisitServiceImpl.around())"/>
<aop:aspect ref="aspect">
<aop:before method="visitBefore" pointcut-ref="pointcut"></aop:before>
<aop:after method="visitAfter" pointcut-ref="pointcut"></aop:after>
<aop:after-returning method="visitSuccess" pointcut-ref="pointcut"></aop:after-returning>
<aop:around method="visitAround" pointcut-ref="pointcut1"></aop:around>
<!-- 報錯後執行aop:after-throwing -->
<aop:after-throwing method="visitThrow" pointcut-ref="pointcut" throwing="ex"></aop:after-throwing>
</aop:aspect>
</aop:config>
注,對於execution()
1、execution(): 表示式主體 (必須加上execution)。
2、第一個* 號:表示返回值型別,* 號表示所有的型別。
3、包名:表示需要攔截的包名,後面的兩個句點表示當前包和當前包的所有子包,cn.smd.service.impl包、子孫包下所有類的方法。
4、第二個* 號:表示類名,* 號表示所有的類。
5、* (..):最後這個星號表示方法名,* 號表示所有的方法,後面括弧裡面表示方法的引數,兩個句點表示任何引數。
書寫的注意事項:execution(* cn.smd.service.impl..(..))
建立一個測試類
public class visitTest {
@Test
public void VisitTest(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext_AOP.xml");
VisitService visitService = app.getBean(VisitService.class);
try {
visitService.visit("agree");
} catch (Exception e) {
e.printStackTrace();
}
try {
visitService.visit("ok");
} catch (Exception e) {
e.printStackTrace();
}
visitService.around();
}
}
測試執行
口令:
agree
請求成功,歡迎
輸入完成
口令:
ok
請求失敗,拒絕
輸入完成
-------環繞-------
環繞通知
-------環繞-------
總結
- SpringAOP進一步降低元件的耦合,實現解耦合
- 可以更好的監控程式,進行許可權攔截
- 注:學習AOP設定注入時需要注意出現報錯時各個通知的狀態
以上就是以註解實現SpringAOP框架設定注入的實現,如有錯誤,麻煩指出,感謝耐心到現在的朋友ᕕ( ᐛ )ᕗ ---By 不斷努力的Yang