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

 

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