四种常用通知类型
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.learn</groupId><artifactId>day03_learn_04adviceType</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.7</version></dependency></dependencies></project>
package com.learn.utils;import org.aspectj.lang.ProceedingJoinPoint;/*** 用于記錄日志的工具類,它里面提供了公共的代碼*/
public class Logger {/*** 前置通知*/public void beforePrintLog(){System.out.println("前置通知Logger類中的beforePrintLog方法開始記錄日志了。。。");}/*** 后置通知*/public void afterReturningPrintLog(){System.out.println("后置通知Logger類中的afterReturningPrintLog方法開始記錄日志了。。。");}/*** 異常通知*/public void afterThrowingPrintLog(){System.out.println("異常通知Logger類中的afterThrowingPrintLog方法開始記錄日志了。。。");}/*** 最終通知*/public void afterPrintLog(){System.out.println("最終通知Logger類中的afterPrintLog方法開始記錄日志了。。。");}/*** 環繞通知* 問題:* 當我們配置了環繞通知之后,切入點方法沒有執行,而通知方法執行了。* 分析:* 通過對比動態代理中的環繞通知代碼,發現動態代理的環繞通知有明確的切入點方法調用,而我們的代碼中沒有。* 解決:* Spring框架為我們提供了一個接口:ProceedingJoinPoint。該接口有一個方法proceed(),此方法就相當于明確調用切入點方法。* 該接口可以作為環繞通知的方法參數,在程序執行時,spring框架會為我們提供該接口的實現類供我們使用。** spring中的環繞通知:* 它是spring框架為我們提供的一種可以在代碼中手動控制增強方法何時執行的方式。*/public Object aroundPringLog(ProceedingJoinPoint pjp){Object rtValue = null;try{Object[] args = pjp.getArgs();//得到方法執行所需的參數System.out.println("Logger類中的aroundPringLog方法開始記錄日志了。。。前置");rtValue = pjp.proceed(args);//明確調用業務層方法(切入點方法)System.out.println("Logger類中的aroundPringLog方法開始記錄日志了。。。后置");return rtValue;}catch (Throwable t){System.out.println("Logger類中的aroundPringLog方法開始記錄日志了。。。異常");throw new RuntimeException(t);}finally {System.out.println("Logger類中的aroundPringLog方法開始記錄日志了。。。最終");}}
}
package com.learn.service;/*** 賬戶的業務層接口*/
public interface IAccountService {/*** 模擬保存賬戶*/void saveAccount();/*** 模擬更新賬戶* @param i*/void updateAccount(int i);/*** 刪除賬戶* @return*/int deleteAccount();
}
package com.learn.service.impl;import com.learn.service.IAccountService;/*** 賬戶的業務層實現類*/
public class AccountServiceImpl implements IAccountService{public void saveAccount() {System.out.println("執行了保存");
// int i=1/0;}public void updateAccount(int i) {System.out.println("執行了更新"+i);}public int deleteAccount() {System.out.println("執行了刪除");return 0;}
}
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 配置srping的Ioc,把service對象配置進來--><bean id="accountService" class="com.learn.service.impl.AccountServiceImpl"></bean><!-- 配置Logger類 --><bean id="logger" class="com.learn.utils.Logger"></bean><!--配置AOP--><aop:config><!-- 配置切入點表達式 id屬性用于指定表達式的唯一標識。expression屬性用于指定表達式內容此標簽寫在aop:aspect標簽內部只能當前切面使用。它還可以寫在aop:aspect外面,此時就變成了所有切面可用--><aop:pointcut id="pt1" expression="execution(* com.learn.service.impl.*.*(..))"></aop:pointcut><!--配置切面 --><aop:aspect id="logAdvice" ref="logger"><!-- 配置前置通知:在切入點方法執行之前執行<aop:before method="beforePrintLog" pointcut-ref="pt1" ></aop:before>--><!-- 配置后置通知:在切入點方法正常執行之后值。它和異常通知永遠只能執行一個<aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning>--><!-- 配置異常通知:在切入點方法執行產生異常之后執行。它和后置通知永遠只能執行一個<aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>--><!-- 配置最終通知:無論切入點方法是否正常執行它都會在其后面執行<aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>--><!-- 配置環繞通知 詳細的注釋請看Logger類中--><aop:around method="aroundPringLog" pointcut-ref="pt1"></aop:around></aop:aspect></aop:config></beans>
package com.learn.test;import com.learn.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** 測試AOP的配置*/
public class AOPTest {public static void main(String[] args) {//1.獲取容器ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");//2.獲取對象IAccountService as = (IAccountService)ac.getBean("accountService");//3.執行方法as.saveAccount();}
}
?
總結
- 上一篇: spring基于XML的AOP-编写必要
- 下一篇: 基于注解的AOP实现事务控制及问题分析