通知分为前置通知、后置通知、异常通知、后置返回通知、环绕通知
其中环绕通知中相当于包含了前置通知、后置通知、异常通知 外加一个最终通知
直接上代码
pom文件中导包
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.9.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> </dependencies>
接口中的三个方法
public interface IAccountService {
void saveAccount();
void updateAccount(int i,int j);
int deleteAccount();
}
实现类中的三个方法
public class AccountServiceImpl implements IAccountService {
public void saveAccount() {
System.out.println("保存账户信息");
}
public void updateAccount(int i,int j) {
int m= 1/0; //测试异常通知时可以解开注释
System.out.println("修改金额:"+i);
}
public int deleteAccount() {
System.out.println("删除账户");
return 0;
}
}
工具Logger中增加一个通知方法
public class Logger {
public void beforePrintLogger(){
System.out.println("前置通知打印日志。。。");
}
public void afterPrintLogger(){
System.out.println("后置通知打印日志。。。");
}
public void retrunPrintLogger(){
System.out.println("返回通知通知打印日志。。。");
}
public void exceptionPrintLogger(){
System.out.println("异常通知打印日志。。。");
}
public Object aroundPrintLogger(ProceedingJoinPoint pjp){
Object rtValue=null;
try {
System.out.println("环绕通知打印日志。。。业务方法执行前的代码相当于前置通知");
Object[] args=pjp.getArgs();
rtValue = pjp.proceed(args);
System.out.println("环绕通知打印日志。。。业务方法执行厚的代码相当于后置通知");
return rtValue;
} catch (Throwable throwable) { //这里的异常类型必须是Throwable类型
System.out.println("环绕通知打印日志。。。这里相当于异常通知");
throw new RuntimeException(throwable);
}
finally {
System.out.println("环绕通知打印日志。。。这里相当于返回通知");
}
}
}
配置Bean.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 id="accountService" class="com.itheima.aop.AccountServiceImpl"></bean>
<bean id="logger" class="com.itheima.utils.Logger"></bean>
<!--com.itheima.aop.AccountServiceImpl.saveAccount()-->
<aop:config>
<!--pointcut可以放置到切面外所哟切面均可引用,但必须放到引用他的切面的最上边-->
<aop:pointcut id="accountPoint" expression="execution(* *..*(int,int))"></aop:pointcut>
<aop:aspect id="logAdvicer" ref="logger">
<aop:before method="beforePrintLogger" pointcut="execution(* *..*(int,int))"></aop:before>
<aop:after method="afterPrintLogger" pointcut-ref="accountPoint"></aop:after>
<aop:after-returning method="retrunPrintLogger" pointcut-ref="accountPoint"></aop:after-returning>
<aop:after-throwing method="exceptionPrintLogger" pointcut-ref="accountPoint"></aop:after-throwing>
<aop:around method="aroundPrintLogger" pointcut-ref="accountPoint"></aop:around>
<!--pointcut可以放置在切面内,此时只能当前切面内引用-->
<!--<aop:pointcut id="accountPoint" expression="execution(* *..*(int,int))"></aop:pointcut>-->
</aop:aspect>
</aop:config>
</beans>
测试类
public class Client {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("Bean.xml");
IAccountService accountService = (IAccountService)ac.getBean("accountService");
// accountService.saveAccount();
accountService.updateAccount(1,2);
// accountService.deleteAccount();
}
}