1. 程式人生 > 其它 >還不理解springAOP系列第三篇,帶你學習spring的面向切面程式設計之環繞通知<aop:around/>

還不理解springAOP系列第三篇,帶你學習spring的面向切面程式設計之環繞通知<aop:around/>

技術標籤:AOPspring面向切面程式設計aop面向切面程式設計環繞通知

第二篇中,我們已經學習了前置通知和後置通知等,本篇主要講解環繞通知,環繞通知相對於前置和後置通知來說,有明顯的優勢。使用環繞通知,我們可以完成前置通知和後置通知所實現的相同功能,而且只需在一個方法中實現。因為整個通知邏輯是在一個方法內實現的,所以不需要使用多個方法。

環繞通知在XML檔案中的配置方法與其他型別通知沒有太大差異,我們只需使用<aop:around>標籤,同時,指定切點和通知方法的名字即可。如下:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
        
        <bean id="accountService" class="cn.com.lzxh.service.impl.AccountServiceImpl"></bean>
        
        <!-- 註冊日誌bean -->
        <bean id="logger" class="cn.com.lzxh.utils.Logger"></bean>
        
        <!-- 配置AOP -->
        <aop:config>
        	<aop:pointcut id="expre" expression="execution(public void cn.com.lzxh.service.impl.AccountServiceImpl.saveAccount())"/>
        	<!-- 配置切面 -->
        	<aop:aspect id="aspect" ref="logger">
        		<!-- 配置環繞通知 -->
        		<aop:around method="arroundLog" pointcut-ref="expre"/>
        	</aop:aspect>
        </aop:config>
        <!-- 加入以下配置,防止spring AOP代理混用導致異常 -->
        <aop:aspectj-autoproxy proxy-target-class="true"/>
        
</beans>

但是,環繞通知的方法必須接收一個ProceedingJoinPoint型別的形參,ProceedingJoinPoint是spring提供的一個介面,這個介面有一個proceed()方法,呼叫這個方法就相當於呼叫了切點方法。否則,使用環繞通知時,程式只會執行環繞通知的內容,不會執行切點方法。程式碼如下:

package cn.com.lzxh.utils;

import org.aspectj.lang.ProceedingJoinPoint;

public class Logger {

	//環繞通知
	public void arroundLog(ProceedingJoinPoint pjp) {
		Object[] args = pjp.getArgs();
		try {
			System.out.println("前置通知");
			pjp.proceed(args);
			System.out.println("後置通知");
		} catch (Throwable e) {
			System.out.println("異常通知");
			e.printStackTrace();
		} finally {
			System.out.println("最終通知");
		}
	}
}

實現類:

package cn.com.lzxh.service.impl;

import cn.com.lzxh.service.AccountService;

public class AccountServiceImpl implements AccountService {

	@Override
	public void saveAccount() {
		System.out.println("儲存資料。。。");
	}

}

測試類:

package cn.com.lzxh.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.com.lzxh.service.AccountService;
import cn.com.lzxh.service.impl.AccountServiceImpl;

public class TestAOP {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
		AccountService as = ac.getBean("accountService", AccountServiceImpl.class);
		as.saveAccount();
	}

}

執行結果為: