使用Spring Boot的AOP处理自定义注解

栏目: Java · 发布时间: 8年前

内容简介:使用Spring Boot的AOP处理自定义注解

上一篇文章 Java 注解介绍讲解了下Java注解的基本使用方式,并且通过自定义注解实现了一个简单的测试工具;本篇文章将介绍如何使用Spring Boot的AOP来简化处理自定义注解,并将通过实现一个简单的方法执行时间统计 工具 为样例来讲解这些内容。

AOP概念

面向侧面的程序设计(aspect-oriented programming,AOP,又译作面向方面的程序设计、观点导向编程、剖面导向程序设计)是计算机科学中的一个术语,指一种程序设计范型。该范型以一种称为侧面(aspect,又译作方面)的语言构造为基础,侧面是一种新的模块化机制,用来描述分散在对象、类或函数中的横切关注点(crosscutting concern)。

侧面的概念源于对面向对象的程序设计的改进,但并不只限于此,它还可以用来改进传统的函数。与侧面相关的编程概念还包括元对象协议、主题(subject)、混入(mixin)和委托。

注释:以上定义源自中文维基百科(如果访问不了,可以通过修改系统的hosts文件访问, 198.35.26.96 zh.wikipedia.org #中文维基百科 ,只能帮到这了,如果还是上不了,那就麻烦上网搜索下怎么修改系统的hosts文件,不同系统下hosts文件位置不一样,如果是 Linux 或者Mac系统,我就直接告诉你吧,一般文件路径是 /etc/hosts ),AOP这个词的翻译有点和国内主流叫法不一致,国内主流都把AOP译做「面向切面编程」,大家不要拘泥于叫法,知道指的是同一个东西即可。

估计,你看了这个定义也是懵的,如果想深入了解可以去知乎看看大佬们是如何掰扯的 什么是面向切面编程AOP? 。我这边还是就直接上例子了吧。

Spring Boot的AOP环境准备

pom.xml 中引入相应的依赖模块

<!-- Spring Boot依赖包 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.1.RELEASE</version>
</parent>
<dependencies>
    <!-- AOP依赖模块 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <!-- Web依赖模块 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

先实现一个简单的Web请求处理

一个简单的处理Web请求的Controller。

package com.craneyuan.controller;

import com.craneyuan.service.IHelloWorldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloWorldController {
    @Autowired
    private IHelloWorldService helloWorldService;

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello(String name) {
        return helloWorldService.getHelloMessage(name);
    }
}

一个简单的HelloWorld服务实现类,接口的定义我就不展示代码了。

package com.craneyuan.service.impl;

import com.craneyuan.annotation.AnalysisActuator;
import com.craneyuan.service.IHelloWorldService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
public class HelloWorldServiceImpl implements IHelloWorldService {

    public String getHelloMessage(String name) {
        return "Hello " + Optional.ofNullable(name).orElse("World!");
    }

}

这样一个简单的Web服务就弄好了,你可以启动项目用 curl 命令调用试下,例如: curl -XGET -i "http://127.0.0.1:8080/hello?name=Java" ,如果一切顺利的话,你将会得到类似下面这样的响应:

HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 11
Date: Thu, 11 Jan 2018 09:45:38 GMT

Hello Java

使用自定义注解来统计方法的执行时间

先定义一个用来统计方法执行时间的注解。

package com.craneyuan.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnalysisActuator {
    String note() default "";
}

然后定义一个切面,来处理刚刚定义的注解。

package com.craneyuan.aspect;

import com.craneyuan.annotation.AnalysisActuator;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AnalysisActuatorAspect {
    final static Logger log = LoggerFactory.getLogger(AnalysisActuatorAspect.class);

    ThreadLocal<Long> beginTime = new ThreadLocal<>();

    @Pointcut("@annotation(analysisActuator)")
    public void serviceStatistics(AnalysisActuator analysisActuator) {
    }

    @Before("serviceStatistics(analysisActuator)")
    public void doBefore(JoinPoint joinPoint, AnalysisActuator analysisActuator) {
        // 记录请求到达时间
        beginTime.set(System.currentTimeMillis());
        log.info("cy666 note:{}", analysisActuator.note());
    }

    @After("serviceStatistics(analysisActuator)")
    public void doAfter(AnalysisActuator analysisActuator) {
        log.info("cy666 statistic time:{}, note:{}", System.currentTimeMillis() - beginTime.get(), analysisActuator.note());
    }

}

最后,只要在需要统计执行时间的方法上加上 @AnalysisActuator 注解就行了。

package com.craneyuan.service.impl;

import com.craneyuan.annotation.AnalysisActuator;
import com.craneyuan.service.IHelloWorldService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
public class HelloWorldServiceImpl implements IHelloWorldService {

    @AnalysisActuator(note = "获取聊天信息方法")
    public String getHelloMessage(String name) {
        return "Hello " + Optional.ofNullable(name).orElse("World!");
    }

}

启动项目,用 curl 命令随便调用一下,如果顺利的话就可以观察到切面打印的日志了。

...
cy666 statistic time:4, note:获取聊天信息方法

参考文章


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design for Hackers

Design for Hackers

David Kadavy / Wiley / 2011-10-18 / USD 39.99

Discover the techniques behind beautiful design?by deconstructing designs to understand them The term ?hacker? has been redefined to consist of anyone who has an insatiable curiosity as to how thin......一起来看看 《Design for Hackers》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具