所有分类
  • 所有分类
  • 未分类

Spring之AOP-控制AOP的执行顺序

简介

本文用示例介绍Spring(SpringBoot)的AOP的执行顺序。

公共代码

Service

package com.example.demo.service;

import com.example.demo.entity.User;

public interface UserService {
    public void printUser(User user);
}
package com.example.demo.service.impl;

import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
    @Override
    public void printUser(User user) {
        if (user == null) {
            throw new RuntimeException("检查用户参数是否为空");
        }
        System.out.print("id = " + user.getId());
        System.out.print("\t userName = " + user.getUserName());
        System.out.println("\t note = " + user.getNote());
    }
}

Controller

package com.example.demo.controller;

import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@RequestMapping("/user")
@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/print")
    @ResponseBody
    public User testPrint(User user) {
        userService.printUser(user);
        return user;
    }

    @RequestMapping("/add")
    @ResponseBody
    @OperationLog(type = "添加", desc = "添加数据")
    public User testAdd(User user) {
        return user;
    }

    @RequestMapping("/update")
    @ResponseBody
    @OperationLog(type = "更新", desc = "更新数据")
    public User testUpdate(User user) {
        userService.printUser(user);
        return user;
    }
}

启动类

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoSpringaopSimpleApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoSpringaopSimpleApplication.class, args);
    }
}

Entity

package com.example.demo.entity;

import lombok.Data;

@Data
public class User {
    private Integer id;
    private String userName;
    private String note;
}

AOP类的顺序控制

可以用@Order来控制切面的执行顺序,当多个切面类都会执行时@Order里的值越小的越先执行。(也可以这样做:切面类实现org.springframework.core.Ordered接口,覆写getOrder()方法)。

AOP类1

package com.example.demo.aspect;

import com.example.demo.annotation.OperationLog;
import com.example.demo.common.util.JsonUtil;
import com.example.demo.entity.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
@Order(1)
public class SimpleAspect {
    @Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.printUser(..))")
    public void pointCut() {

    }

    @Before("pointCut()")
    public void before() {
        System.out.println("####################### SimpleAspect.before #######################");
    }

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("####################### SimpleAspect.around #######################");
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        System.out.println("joinPoint.getTarget().toString()  : " + joinPoint.getTarget().toString());
        System.out.println("methodSignature.getName()         : " + methodSignature.getName());
        System.out.println("method.getName()                  : " + method.getName());
        System.out.println("method.getReturnType().getName()  : " + method.getReturnType().getName());

        Object[] objects = joinPoint.getArgs();
        System.out.println(JsonUtil.toJson(objects));

        System.out.println("------------------- SimpleAspect.around: around before -------------------");
        Object object = joinPoint.proceed();
        System.out.println("------------------- SimpleAspect.around: 返回值 -------------------");
        System.out.println(JsonUtil.toJson(object));
        System.out.println("------------------- SimpleAspect.around: around after -------------------");

        return object;
    }

    @After("pointCut()")
    public void after() {
        System.out.println("####################### SimpleAspect.after #######################");
    }

    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("####################### SimpleAspect.afterReturning #######################");
    }

    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("####################### SimpleAspect.afterThrowing #######################");
    }
}

AOP类2 

package com.example.demo.aspect;

import com.example.demo.common.util.JsonUtil;
import com.example.demo.entity.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
@Order(2)
public class OrderTestAspect {
    @Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.printUser(..))")
    public void pointCut() {

    }

    @Before("pointCut()")
    public void before() {
        System.out.println("####################### OrderTestAspect.before #######################");
    }

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("####################### OrderTestAspect.around #######################");
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        System.out.println("joinPoint.getTarget().toString()  : " + joinPoint.getTarget().toString());
        System.out.println("methodSignature.getName()         : " + methodSignature.getName());
        System.out.println("method.getName()                  : " + method.getName());
        System.out.println("method.getReturnType().getName()  : " + method.getReturnType().getName());

        Object[] objects = joinPoint.getArgs();
        System.out.println(JsonUtil.toJson(objects));

        System.out.println("------------------- OrderTestAspect.around: around before -------------------");
        Object object = joinPoint.proceed();
        System.out.println("------------------- OrderTestAspect.around: 返回值 -------------------");
        System.out.println(JsonUtil.toJson(object));
        System.out.println("------------------- OrderTestAspect.around: around after -------------------");

        return object;
    }

    @After("pointCut()")
    public void after() {
        System.out.println("####################### OrderTestAspect.after #######################");
    }

    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("####################### OrderTestAspect.afterReturning #######################");
    }

    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("####################### OrderTestAspect.afterThrowing #######################");
    }
}

测试

后端结果

####################### SimpleAspect.around #######################
joinPoint.getTarget().toString()  : com.example.demo.service.impl.UserServiceImpl@1d6f5d26
methodSignature.getName()         : printUser
method.getName()                  : printUser
method.getReturnType().getName()  : void
[{"id":321,"userName":"Tony","note":"abc"}]
------------------- SimpleAspect.around: around before -------------------
####################### SimpleAspect.before #######################
####################### OrderTestAspect.around #######################
joinPoint.getTarget().toString()  : com.example.demo.service.impl.UserServiceImpl@1d6f5d26
methodSignature.getName()         : printUser
method.getName()                  : printUser
method.getReturnType().getName()  : void
[{"id":321,"userName":"Tony","note":"abc"}]
------------------- OrderTestAspect.around: around before -------------------
####################### OrderTestAspect.before #######################
id = 321	 userName = Tony	 note = abc
####################### OrderTestAspect.afterReturning #######################
####################### OrderTestAspect.after #######################
------------------- OrderTestAspect.around: 返回值 -------------------
null
------------------- OrderTestAspect.around: around after -------------------
####################### SimpleAspect.afterReturning #######################
####################### SimpleAspect.after #######################
------------------- SimpleAspect.around: 返回值 -------------------
null
------------------- SimpleAspect.around: around after -------------------

可以发现,优先级高的,before先执行,after后执行。

AOP方法的顺序控制

有人说:单个AOP类里边,可以用@Order来控制方法的执行顺序。但是,我测试是不可以的!

AOP类

package com.example.demo.aspect;

import com.example.demo.annotation.OperationLog;
import com.example.demo.common.util.JsonUtil;
import com.example.demo.entity.User;
import com.sun.org.apache.regexp.internal.RE;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class SimpleAspect {
    @Order(2)
    @Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.printUser(..))")
    public void pointCut1() {

    }

    @Order(1)
    @Pointcut("@annotation(com.example.demo.annotation.OperationLog)")
    public void pointCut2() {

    }

    @Before("pointCut1()")
    public void before1() {
        System.out.println("############################ SimpleAspect.before 1 ############################");
    }

    @Before("pointCut2()")
    public void before2() {
        System.out.println("############################ SimpleAspect.before 2 ############################");
    }
}

Service类

package com.example.demo.service.impl;

import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
    @Override
    @OperationLog
    public void printUser(User user) {
        if (user == null) {
            throw new RuntimeException("检查用户参数是否为空");
        }
        System.out.print("id = " + user.getId());
        System.out.print("\t userName = " + user.getUserName());
        System.out.println("\t note = " + user.getNote());
    }
}

测试

访问:http://localhost:8080/doc.html

结果:(没有按照执行的顺序执行)

############################ SimpleAspect.before 1 ############################
############################ SimpleAspect.before 2 ############################
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录