Spring Boot: 自定义注解结合切面

注解看起来是一个很神奇的东西,也是一个解耦的利器。直入正题,从创建一个自定义的注解开始。

1.创建注解@MyLogger,添加属性message,fallback。这里Target对象选择方法,Retention选择运行时。Ctrl+点击可以查看ElementType的可选值,里面有非常详尽的注释,这里不再赘述。

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyLogger {
    String message() default "";

    String fallback() default "fallbackMethod";
}

2.创建切面MyLoggerAspectj,里面做一个增强处理,如果message为add,返回结果为原方法+fallback设定的方法。

@Aspect
@Component
public class MyLoggerAspectj {
    Logger logger = LoggerFactory.getLogger(MyLoggerAspectj.class);

    private String PROCESS_TYPE_ADD = "add";

    @Around("@annotation(myLogger)")
    public Object around(ProceedingJoinPoint proceedingJoinPoint, MyLogger myLogger) throws Throwable {

        Object o1 = proceedingJoinPoint.proceed();

        if (PROCESS_TYPE_ADD.equals(myLogger.message())) {
            //走fallback
            String methodName = myLogger.fallback();
            try {
                MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
                Class[] types = signature.getParameterTypes();
                Method method = proceedingJoinPoint.getTarget().getClass().getMethod(methodName, types);
                try {
                    Object o2 = method.invoke(proceedingJoinPoint.getTarget(), proceedingJoinPoint.getArgs());
                    ArrayList list = new ArrayList();
                    if (o1 instanceof List) {
                        list.addAll((ArrayList) o1);
                    }
                    list.add(o2);
                    return list;
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
        return o1;
    }

}

3.在Service层添加新接口及方法。

    @MyLogger(message = "add", fallback = "createUser")
    @Override
    public List<User> getAno(Integer id) {
        List list = new ArrayList();
        list.add(userMapper.getUserById(id));
        return list;
    }

    public User createUser(Integer id) {
        User user = new User();
        user.setId(-1);
        user.setUserName("系统自动创建用户");
        user.setStatus(-1);
        return user;
    }

4.Controller层添加方法。

    @RequestMapping("/ano")
    public List<User> ano(Integer id) throws Throwable {
        return userService.getAno(id);
    }

5.访问urlhttp://localhost:8080/ano?id=1。确认结果包含自动创建用户。

通过以上几个步骤,很轻松可以创建一个自定义的注解。完整工程:https://github.com/showsys20/spring-demo-cm.git

以上过程,实际上是常规开发时的一个模式,从下往上实装,dao->service->controller。

这里只是演示了一个简单的应用,实际上可以用类似的方式,在切面里加上guava包的RateLimiter或者Redis来实现流量控制,服务降级等功能。


版权声明:本文为u012129340原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。