首先要说明一点,spring基于注解的四种通知会有bug,所以实际开发,建议使用基于注解的环绕通知
首先pom依赖如下
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
</dependencies>
AccountService接口
package com.lp.service;
/**
* @Date 2020/5/29 14:37
* @Author luopeng
*/
public interface AccountService {
/**
* 模拟保存账户
*/
void saveAccount();
/**
* 模拟更新账户
*/
void updateAccount();
/**
* 模拟删除账户
*/
void deleteAccount(int id);
}
实现类
package com.lp.service.impl;
import com.lp.service.AccountService;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;
/**
* @Date 2020/5/29 14:40
* @Author luopeng
*/
@Service("accountService")
public class AccountServiceImpl implements AccountService {
public void saveAccount() {
System.out.println("执行了保存!");
int i = 1/0;
}
public void updateAccount() {
System.out.println("执行了更新!");
}
public void deleteAccount(int id) {
System.out.println("执行了删除!"+id);
}
}
写我们增强代码的工具类
package com.lp.utils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 用于记录日志的工具类,它里面提供了公共方法
*
* @Date 2020/5/29 14:41
* @Author luopeng
*/
@Component
@Aspect
public class Logger {
@Pointcut("execution(* com.lp.service.impl.*.*(..))")
private void pt1(){}
/**
* 前置通知
*/
// @Before("pt1()")
public void beforePrintLog() {
System.out.println("前置通知Logger类里面的printLog开始日志输入。。。");
}
/**
* 后置通知
*/
// @AfterReturning("pt1()")
public void afterReturningPrintLog() {
System.out.println("后置通知Logger类里面的printLog开始日志输入。。。");
}
/**
* 异常通知
*/
// @AfterThrowing("pt1()")
public void afterThrowingPrintLog() {
System.out.println("异常通知Logger类里面的printLog开始日志输入。。。");
}
/**
* 最终通知
*/
// @After("pt1()")
public void afterPrintLog() {
System.out.println("最终通知Logger类里面的printLog开始日志输入。。。");
}
/**
* spring为我们提供了一个接口ProceedingJoinPoint
* 该接口有一个proceed方法,此方法相当于明确调用切入点方法,
* 我们可以将spring提供的接口作为方法参数,我们可调用该接口的实现类方法
*spring中的环绕通知:
* 我们可以手动控制增强方法何时执行
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("pt1()")
public Object arruondPrintLog(ProceedingJoinPoint proceedingJoinPoint) {
Object rtValue = null;
//获取方法所需参数
Object[] args = proceedingJoinPoint.getArgs();
System.out.println("Logger类里面的printLog开始日志输入。。。前置");
try {
rtValue = proceedingJoinPoint.proceed(args);
System.out.println("Logger类里面的printLog开始日志输入。。。后置");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("Logger类里面的printLog开始日志输入。。。异常");
}finally {
System.out.println("Logger类里面的printLog开始日志输入。。。最终");
}
return rtValue;
}
}
此时我们需要spring的一个配置类
package com.lp.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* @Date 2020/5/29 19:47
* @Author luopeng
*/
@Configuration
@ComponentScan(basePackages = "com.lp")
@EnableAspectJAutoProxy
public class Config {
}
测试类如下
package com.lp.test;
import com.lp.config.Config;
import com.lp.service.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
/**
* @Date 2020/5/29 15:06
* @Author luopeng
*/
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
public class AOPTest {
@Autowired
private AccountService accountService;
@Test
public void test(){
accountService.saveAccount();
}
}
建议大家自己看完代码,理解记忆下来敲出来,虽然过程可能有点劳累,但你要相信,你没遇到一个错误就是你最大的收获,我刚刚找bug找了一个小时,就因为我RunWith里面的value值写错了,我去看了一下Runner的子类,就很大意的写成了BlockJUnit4ClassRunner,真想啪啪打自己的脸!不过以后都忘不了它给我带来的痛了!把它吞肚子里了,别想再一次欺负我!