java-spring-AOP面向切面编程

Spring AOP是面向切面编程,切面有几个重要概念:

切面:连接点、切点、通知所在的【类】就是切面
切点:连接点的集合
连接点:可以理解为spring的方法
通知:切入切点的时机before、after等 业务

 

在spring-boot中的简单应用

1:在pom中加入aop的依赖:

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

2:编辑切面:

这是一个关于日志的切面(类),

通过@Pointcut("execution(* com.teligen.dazt.learn.spring.aop.service..*.*(..))")设置切点

通过 @Before("logPointCut()")   @After("logPointCut()")  设置通知业务。


import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * 一个日志的切面
 */
@Component
@Aspect
public class LogAspect {

    private Logger logger = LoggerFactory.getLogger(LogAspect.class);

    /**
     * 日志切点
     */
    @Pointcut("execution(* com.teligen.dazt.learn.spring.aop.service..*.*(..))")
    public void logPointCut(){
    }

    /**
     * 日志开始
     */
    @Before("logPointCut()")
    public void logBefore(){
//        logger.info("before ...");
        logger.info("before");
    }

    /**
     * 日志结束
     */
    @After("logPointCut()")
    public void logAfter(){
//        logger.info("after ...");
        logger.info("after");
    }

    /**
     * 日志环绕
     */
    @Around("logPointCut()")
    public void logAround(ProceedingJoinPoint joinPoint){
        try {
            logger.info("around start");
            Signature signature = joinPoint.getSignature();
            //方法名
            String methodName = signature.getName();
            //类型
            String serviceName = signature.getDeclaringTypeName();
            // 参数名数组
            String[] parameterNames = ((MethodSignature) signature).getParameterNames();
            // 构造参数组集合
            List<Object> argList = new ArrayList<>();
            for (Object arg : joinPoint.getArgs()) {
                // request/response无法使用toJSON
                if (arg instanceof HttpServletRequest) {
                    argList.add("request");
                } else if (arg instanceof HttpServletResponse) {
                    argList.add("response");
                } else {
                    argList.add(JSON.toJSON(arg));
                }
            }
            try {
                logger.info("{} -> 方法({}) -> 参数:{} - {}", serviceName, methodName, JSON.toJSON(parameterNames), JSON.toJSON(argList));
            } catch (Exception e) {
                logger.error("参数获取失败: {}", e.getMessage());
            }

            long startTime = System.currentTimeMillis();
            Object data = joinPoint.proceed();
            logger.info("joinPoint.proceed 执行结果: "+data);
            long endTime = System.currentTimeMillis();
            logger.info("around end 时间:"+(endTime - startTime));
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }


}

3:编写相关的测试方法

package com.teligen.dazt.learn.spring.aop.service.impl;

import com.teligen.dazt.learn.spring.aop.service.MyService;
import org.springframework.stereotype.Service;

@Service
public class MyServiceImpl implements MyService {
    @Override
    public String doAnalyse() throws InterruptedException {
        System.out.println("开始进行分析...");
        Thread.sleep(1000);
        System.out.println("结束分析...");
        return "执行成功";
    }
}

运行结果:

2020-03-03 15:58:13.046  INFO 15016 --- [nio-8980-exec-1] c.t.dazt.learn.spring.aop.LogAspect      : around start
2020-03-03 15:58:13.354  INFO 15016 --- [nio-8980-exec-1] c.t.dazt.learn.spring.aop.LogAspect      : com.teligen.dazt.learn.spring.aop.service.impl.MyServiceImpl -> 方法(doAnalyse) -> 参数:[] - []
2020-03-03 15:58:13.397  INFO 15016 --- [nio-8980-exec-1] c.t.dazt.learn.spring.aop.LogAspect      : before
开始进行分析...
结束分析...
2020-03-03 15:58:14.406  INFO 15016 --- [nio-8980-exec-1] c.t.dazt.learn.spring.aop.LogAspect      : joinPoint.proceed 执行结果: 执行成功
2020-03-03 15:58:14.406  INFO 15016 --- [nio-8980-exec-1] c.t.dazt.learn.spring.aop.LogAspect      : around end 时间:1009
2020-03-03 15:58:14.407  INFO 15016 --- [nio-8980-exec-1] c.t.dazt.learn.spring.aop.LogAspect      : after

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章