1、前言
之前看到别人写的代码,没有设置任何东西,发现结果值变化了。比如,插入和修改数据的时候经常记录操作人的信息。不用设值,入库就会有操作人的信息。还有其他一些日志、监控等。这都是采用了aop切面的方式。
2、依赖引入
<!-- 切面 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
3、demo
本文通过模拟插入一条数据,在插入数据时,修改对象属性。
测试类:
@RunWith(SpringRunner.class)
@SpringBootTest
public class BootFooApplicationTests {
@Autowired
private TestService testService;
@Test
public void contextLoads() {
BookDTO book = new BookDTO();
book.setName("hello");
System.out.println("数据插入前!"+ book.getName());
testService.insertBook(book);
System.out.println("数据插入成功后!"+ book.getName());
}
}
插入数据的实现类:
@Service
public class TestServiceImpl implements TestService{
@Override
public int insertBook(BookDTO book) {
System.out.println("新增书籍成功!");
return 1;
}
}
创建AOP切面:
/**
* 创建切面
* @author ws
*/
@Aspect
@Component
public class AopConfig {
/**
* 创建切入点:execution表达式指定针对某个(些)方法,进行切入
*/
@Pointcut("execution(* com.simonking.ws.bootFoo.service.TestService.insertBook(..))")
public void myPointCut() {}
/**
* 环绕通知:最先执行,在执行proceed()之前执行前置通知,在return之后执行后置通知
*
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("myPointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("①环绕通知前....");
Object obj= (Object) joinPoint.proceed();
System.out.println("③环绕通知后....");
return obj;
}
/**
* 前置通知: 更改参数信息
*
* @param point
*/
@Before("myPointCut()")
public void beforeCut(JoinPoint point) {
Object[] args = point.getArgs();
for (Object object : args) {
if (object instanceof BookDTO) {
BookDTO bookDTO = (BookDTO) object;
bookDTO.setName("123");
}
}
System.out.println("②前置执行中!");
}
/**
* 后置通知
*/
@After("myPointCut()")
public void after(){
System.out.println("④后置通知....");
}
/**
* 在实现类insert返回执行执行,可以拿到返回参数
*
* @param returnVal
*/
@AfterReturning(value="myPointCut()",returning="returnVal")
public void afterReturning(Object returnVal) {
System.out.println("⑥执行后返回中!"+ returnVal);
}
}
4、运行结果
5、参考资料
execution表达式含义:https://www.cnblogs.com/li3807/p/9002683.html