spring aopAOP(面向切面编程)Spring Boot

Spring源码-AOP(三)Springboot与Aop

2017-09-01  本文已影响375人  阿亮私语

前言

把文章在简书同步了之后,有几篇文章被收入专题,还有一篇文章被收入首页,尽管不是什么了不起的事,但是这样也让自己挺开心的,慕课网约我录了一次视频课程,没有通过,让修改下录第二次,想想还是算了,目前的自己水平还是有限,另一方面时间也比较有限,在博客这方面能够持续下去就已经是件很难的事情,其他的以后再说看缘分吧。接下来继续技术的分析。

前两篇主要记录了AOP所用的核心设计模式-代理模式,包含动态代理和静态代理,以及JDK和CGLIB的两种实现方式,接下来开始重点分析Spring-AOP源码相关操作,当然开始也是从概念理解。这个不太好明白,但是第一遍阅读也主要是为了对于框架有个大局观,不需要过度的拘泥于细节。AOP这段计划在9月中之前结束,而下半月主要是SpringMVC相关的源码研究,可能也会结合一点事务和mybatis源码的研究。

参考了很多程序员DD的东西

Spring-Aop相关概念如下:


我把这个图片放在网络上了,欢迎大家前往下载,建议大家先从地址一下载,地址二要耗流量
下载地址
备用地址
相关的概念描述在脑图中有详细解释,当然方便理解,这里我也会记录下来。

项目部署

我们先在springboot中将aop整合进来
在pom.xml引入pom依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

starter中默认添加了@EnableAspectJAutoProxy
设计一个简单的controller入门

@RestController
public class HomeController {
    private Logger logger = Logger.getLogger(getClass());
    @GetMapping("/index")
    public String index(@RequestParam String name){
        logger.info("-----------{name}:{}"+name);
        return "【welcome to aop】:" +name;
    }
}

实现Web层的日志切面

@Aspect
@Component
public class WebLogAspect {
    private Logger logger = Logger.getLogger(getClass());
    @Pointcut("execution(public * com.sunliangliang.springsource.controller..*(..))")
    public void webLog(){}

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
    }
    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        logger.info("RESPONSE : " + ret);
    }
}

运行程序

输出如下日志:

2017-09-01 18:20:34.953  INFO 14696 --- [nio-8888-exec-3] c.s.springsource.aop.WebLogAspect        : URL : http://localhost:8888/index
2017-09-01 18:20:34.953  INFO 14696 --- [nio-8888-exec-3] c.s.springsource.aop.WebLogAspect        : HTTP_METHOD : GET
2017-09-01 18:20:34.953  INFO 14696 --- [nio-8888-exec-3] c.s.springsource.aop.WebLogAspect        : IP : 0:0:0:0:0:0:0:1
2017-09-01 18:20:34.953  INFO 14696 --- [nio-8888-exec-3] c.s.springsource.aop.WebLogAspect        : CLASS_METHOD : com.sunliangliang.springsource.controller.HomeController.index
2017-09-01 18:20:34.953  INFO 14696 --- [nio-8888-exec-3] c.s.springsource.aop.WebLogAspect        : ARGS : [liangliang]
2017-09-01 18:20:34.953  INFO 14696 --- [nio-8888-exec-3] c.s.s.controller.HomeController          : -----------{name}:{}liangliang
2017-09-01 18:20:34.953  INFO 14696 --- [nio-8888-exec-3] c.s.springsource.aop.WebLogAspect        : RESPONSE : 【welcome to aop】:liangliang

优化

由于通过AOP实现,程序得到了很好的解耦,但是也会带来一些问题,比如:我们可能会对Web层做多个切面,校验用户,校验头信息等等,这个时候经常会碰到切面的处理顺序问题。
所以要定义每个切面的优先级,我们需要@Order(i)注解来标识切面的优先级。i值越小,优先级越高。假设我们还有一个切面是CheckNameAspect用来校验name必须为didi,我们为其设置@Order(10),而上文中WebLogAspect设置为@Order(5),所以WebLogAspect有更高的优先级,这个时候执行顺序是这样的:

上一篇下一篇

猜你喜欢

热点阅读