转载于:https://www.cnblogs.com/LemonFive/p/10983875.html
本文基于SpringBoot编写了一个简单的Spring AOPDemo。
maven依赖添加如下
<!--引入SpringBoot的Web模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入AOP依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
注意:在完成了引入AOP依赖包后,不需要去做其他配置。AOP的默认配置属性中,spring.aop.auto属性默认是开启的,也就是说只要引入了AOP依赖后,默认已经增加了@EnableAspectJAutoProxy,不需要在程序主类中增加@EnableAspectJAutoProxy来启用。
web请求入口:对应系统纵向的核心业务模块。
package com.example.demo.aop;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @desc: 核心业务模块
* @author: CSH
**/
@RestController
@RequestMapping("/aopController")
public class AopController {
@RequestMapping(value = "/Curry")
public void Curry(){
System.out.println("库里上场打球了!!");
}
@RequestMapping(value = "/Harden")
public void Harden(){
System.out.println("哈登上场打球了!!");
}
@RequestMapping(value = "/Antetokounmpo")
public void Antetokounmpo(){
System.out.println("字母哥上场打球了!!");
}
@RequestMapping(value = "/Jokic")
public void Jokic(){
System.out.println("约基奇上场打球了!!");
}
@RequestMapping(value = "/Durant/{point}")
public void Durant(@PathVariable("point") int point){
System.out.println("杜兰特上场打球了!!");
}
}
定义切面类:在类上添加@Aspect 和@Component 注解即可将一个类定义为切面类。
@Aspect 注解 使之成为切面类
@Component 注解 把切面类加入到IOC容器中
package com.example.demo.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* @desc: 经纪人切面
* @author: CSH
**/
@Aspect
@Component
public class BrokerAspect {
/**
* 定义切入点,切入点为com.example.demo.aop.AopController中的所有函数
*通过@Pointcut注解声明频繁使用的切点表达式
*/
@Pointcut("execution(public * com.example.demo.aop.AopController.*(..)))")
public void BrokerAspect(){
}
/**
* @description 在连接点执行之前执行的通知
*/
@Before("BrokerAspect()")
public void doBeforeGame(){
System.out.println("经纪人正在处理球星赛前事务!");
}
/**
* @description 在连接点执行之后执行的通知(返回通知和异常通知的异常)
*/
@After("BrokerAspect()")
public void doAfterGame(){
System.out.println("经纪人为球星表现疯狂鼓掌!");
}
/**
* @description 在连接点执行之后执行的通知(返回通知)
*/
@AfterReturning("BrokerAspect()")
public void doAfterReturningGame(){
System.out.println("返回通知:经纪人为球星表现疯狂鼓掌!");
}
/**
* @description 在连接点执行之后执行的通知(异常通知)
*/
@AfterThrowing("BrokerAspect()")
public void doAfterThrowingGame(){
System.out.println("异常通知:球迷要求退票!");
}
}

/**
* @description 使用环绕通知
*/
@Around("BrokerAspect()")
public void doAroundGame(ProceedingJoinPoint pjp) throws Throwable {
try{
System.out.println("经纪人正在处理球星赛前事务!");
pjp.proceed();
System.out.println("返回通知:经纪人为球星表现疯狂鼓掌!");
}
catch(Throwable e){
System.out.println("异常通知:球迷要求退票!");
}
}
环绕通知接受ProceedingJoinPoint作为参数,它来调用被通知的方法。通知方法中可以做任何的事情,当要将控制权交给被通知的方法时,需要调用ProceedingJoinPoint的proceed()方法。当你不调用proceed()方法时,将会阻塞被通知方法的访问。
当通知方法需要传入参数我们又该怎样处理呢?
和之前创建的切面一样,这里的不同点在于切点还声明了要提供给通知方法的参数。
切点表达式args(point)表明传递给GameDataAspect()方法中的int类型参数也会传递到通知中去,参数名point和缺点方法签名中的参数相匹配
package com.example.demo.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* @desc:技术统计
* @author: CSH
**/
@Aspect
@Component
public class GameDataAspect {
/**
* 定义切入点,切入点为com.example.demo.aop.AopController中的所有函数
*通过@Pointcut注解声明频繁使用的切点表达式
*/
@Pointcut("execution(public * com.example.demo.aop.AopController.Durant(int)) && args(point))")
public void GameDataAspect(int point){
}
/**
* @description 使用环绕通知
*/
@Around("GameDataAspect(point)")
public void doAroundGameData(ProceedingJoinPoint pjp,int point) throws Throwable {
try{
System.out.println("球星上场前热身!");
pjp.proceed();
System.out.println("球星本场得到" + point + "分" );
}
catch(Throwable e){
System.out.println("异常通知:球迷要求退票!");
}
}
}
本文代码Github链接https://github.com/LemonFive/SpringBootAopDemo
