Spring AOP 实践

本文介绍了Spring AOP的实践应用,包括切点表达式的使用,通知类型的理解,自定义权限注解的创建以及事务管理的配置。通过具体的示例展示了如何在Service层、Controller层实现切面,以及@Transactional注解的详细属性设置。
摘要由CSDN通过智能技术生成

一、切点表达式基本使用

Service层

@Service
public class NormalService {
    private Logger logger = Logger.getLogger(getClass());

    public void testArgNames(String str,Integer i){
        logger.info("有参正常返回StringInteger");
    }
    public void testArgNames(Integer i,String str,String str2){
        logger.info("有参正常返回IntegerStringString");
    }
    public void testArgNames(){
        logger.info("无参正常返回");
    }
 }

切面

@Aspect
@Component
public class NormalAspect {
    private Logger logger = Logger.getLogger(getClass());
    
    // 拦截参数为任意的testArgNames方法
    @Pointcut(value = "execution(public * com.gome.rec.af.consumer1.service.NormalService.testArgNames(..))")
    public void normalLog() {
    }

    @Before(value = "normalLog()")
    public void before() {
        System.out.println("调用参数为任意的testArgNames方法...");
    }
}

Controller层

@RestController
public class NormalController {
    @Autowired
    private NormalService normalService;
 
    @RequestMapping("testArgNames2")
    public void testArgName(@RequestParam Integer i,String str){
        normalService.testArgNames();
        normalService.testArgNames(str,i);
        normalService.testArgNames(i,str,str);
    }
}

请求localhost:8066/testArgNames2?i=1&str=abc,三个方法都拦截,控制台显示:

在这里插入图片描述

注: 一个Aspect中不可以有两个名字相同的切面

二、通知

@Aspect
public class UserLogAspect {
    private Logger logger = Logger.getLogger(getClass());

    @Pointcut("bean(*Service) && within(com.gome.rec.af.consumer1.service.User*)")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void beforeLog() {
        logger.info("开始执行前置通知 日志记录");
    }

    @After("pointCut()")
    public void afterLog() {
        logger.info("开始执行后置通知 日志记录");
    }

    @AfterReturning("pointCut()")
    public void afterReturningLog() {
        logger.info("方法成功后执行通知 日志记录");
    }

    @AfterThrowing("pointCut()")
    public void afterThrowingLog() {
        logger.info("方法抛出异常后执行通知 日志记录");
    }

    @Around("pointCut()")
    public Object aroundLog(ProceedingJoinPoint joinPoint) {
        Object result = null;
        try {
            logger.info("环绕通知开始 日志记录");
            long start = System.currentTimeMillis();
            // 执行拦截的方法
            result = joinPoint.proceed();
            long end = System.currentTimeMillis();
            logger.info("总共执行时长:" + (end - start) + "毫秒");
            logger.info("环绕通知结束 日志记录");
        } catch (Throwable t) {
            logger.info("出现错误");
        }
        return result;
    }
}

请求打印控制台

在这里插入图片描述

执行顺序:环绕开始-@Before-执行-环绕结束-@After-@AfterReturning
若有异常:环绕开始-@Before-执行-@AfterThrowing-@After-@AfterReturning

三、权限+自定义注解

定义@AuthChecker注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthChecker {
}
@Aspect
public class HttpAopAdviseDefine {

    // @annotation:匹配由指定注解所标注的方法
    @Pointcut("@annotation(com.gome.rec.af.consumer1.aspect.AuthChecker)")
    public void pointcut(){}

    @Around("pointcut()")
    public Object checkAuth(ProceedingJoinPoint joinPoint) throws  Throwable{
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 检查用户所传递的 token 是否合法
        String token = getUserToken(request);
        if (!token.equalsIgnoreCase("123456")) {
            return "错误, 权限不合法!";
        }
        return joinPoint.proceed();
    }
}

只有符合这个格式的请求才可以,否则给出提示

在这里插入图片描述

四、事务应用

最简单就是加入:@Transactional注解,属性如下进行设置即可

propagation 属性:事务的传播行为,默认值为 Propagation.REQUIRED
REQUIRED:如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务
SUPPORTS :如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。
MANDATORY :如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。
REQUIRES_NEW :重新创建一个新的事务,如果当前存在事务,暂停当前的事务。
NOT_SUPPORTED :以非事务的方式运行,如果当前存在事务,暂停当前的事务。
NEVER :以非事务的方式运行,如果当前存在事务,则抛出异常。
NESTED :和 Propagation.REQUIRED 效果一样。
isolation 属性:隔离级别,默认值为 Isolation.DEFAULT,底层数据库默认的隔离级别
timeout 属性:默认为-1,超过时间未提交则回滚,单位为秒
readOnly 属性:默认false,忽略读数据select,则设置为true
rollbackFor 属性:指定能够触发事务回滚的异常类型,可以指定多个异常类型
noRollbackFor 属性

基本的AOP实践就是这些,具体需要是实际中应用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值