一,什麼是AOP
AOP(Aspect Oriented Programming)面向切面程式設計,是Spring框架中的內容,它是針對於一個事件的某個步驟或階段,主要應用於:紀錄檔,事務處理,例外處理等方面,它的原理是:通過過濾,對指定的一些操作直接新增設定好的方法,不需要頻繁的呼叫,在不使用介面的情況下實現java的動態代理。
AOP技術利用一種稱為「橫切」的技術,剖解開封裝物件的內部,將影響多個類的公共行為封裝到一個可重用的模組中,並將其命名為Aspect切面。所謂的切面,簡單來說就是與業務無關,卻為業務模組所共同呼叫的邏輯,將其封裝起來便於減少系統的重複程式碼,降低模組的耦合度,有利用未來的可操作性和可維護性。
利用AOP可以對業務邏輯各個部分進行隔離,從而使業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高開發效率。
Spring AOP 模組提供攔截器來攔截一個應用程式,例如,當執行一個方法時,你可以在方法執行之前或之後新增額外的功能。
二 AOP術語
三 通知的型別
Spring 方面可以使用下面提到的五種通知:
四 Spring 中基於AOP的XML架構
以銀行系統的存款和轉賬流程來說,其中都存在相同的驗證流程,AOP思想則是將這些相同的流程抽離出來,以存錢/轉賬方法為切入點,分別在此切入點之前或之後建立設定。
程式碼展示:
為了在本節的描述中使用 aop 名稱空間標籤,你需要匯入 spring-aop j架構,如下所述:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
</beans> ">
首先建立存款和轉賬的介面
package cn.tb.dao;
public interface BankDao {
//存錢
public void saveMoney();
//轉賬
public void remirt();
}
然後設定相關流程
驗證事務
package cn.tb.impl;
public class AdminCheck {
public void check(){
System.out.println("許可權驗證開始");
}
}
處理和提交事務
package cn.tb.impl;
import org.aspectj.lang.ProceedingJoinPoint;
public class TransactionManager {
public void beginTransaction(){
System.out.println("開始事務處理");
}
public void commitTrnasaction(){
System.out.println("提交事務處理");
}
public void doInceptor(ProceedingJoinPoint point) throws Throwable{
beginTransaction();
point.proceed();
commitTrnasaction();
}
}
執行相關操作
package cn.tb.impl;
import cn.tb.dao.BankDao;
public class BankDaoImpl implements BankDao{
@Override
public void saveMoney() {
System.out.println("正在存錢");
}
@Override
public void remirt() {
System.out.println("正在轉賬");
}
}
紀錄檔寫入
package cn.tb.impl;
public class LogManager {
//紀錄檔
public void writeLog(){
System.out.println("紀錄檔正在寫入");
}
}
最後設定完整的Spring 中基於AOP的XML檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!--注入bean-->
<bean class="cn.tb.impl.AdminCheck" id="adminCheck"></bean>
<bean class="cn.tb.impl.BankDaoImpl" id="bankDao"></bean>
<bean class="cn.tb.impl.LogManager" id="logManager"></bean>
<bean class="cn.tb.impl.TransactionManager" id="transactionManager"></bean>
<!--開始spring aop 面向切面設定-->
<aop:config>
<!--切入點 什麼時機,什麼時候切入-->
<aop:pointcut id="serviceInceptor" expression="execution(* cn.tb.impl.*.*(..))"></aop:pointcut>
<!--前置通知 在一個方法執行之前,執行通知。-->
<aop:aspect ref="adminCheck">
<aop:before method="check" pointcut-ref="serviceInceptor"></aop:before>
</aop:aspect>
<!--環繞通知 在建議方法呼叫之前和之後,執行通知。-->
<aop:aspect ref="transactionManager">
<aop:around method="doInceptor" pointcut-ref="serviceInceptor"></aop:around>
</aop:aspect>
<!--後置通知 在一個方法執行之後,不考慮其結果,執行通知。-->
<aop:aspect ref="logManager">
<aop:after method="writeLog" pointcut-ref="serviceInceptor"></aop:after>
</aop:aspect>
</aop:config>
</beans>
測試
package cn.tb.test;
import cn.tb.dao.BankDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
test1();
System.out.println("-------------");
test2();
}
//存錢
private static void test1() {
ApplicationContext alc = new ClassPathXmlApplicationContext("Spring.xml");
BankDao dao = alc.getBean("bankDao", BankDao.class);
dao.saveMoney();
}
//轉賬
private static void test2() {
ApplicationContext alc = new ClassPathXmlApplicationContext("Spring.xml");
BankDao dao = alc.getBean("bankDao", BankDao.class);
dao.remirt();
}
}
測試結果: