spring aop @aspectj的簡單說明

1.AOP術語圖片
這裏寫圖片描述
2.spring切面應用的無五種通知
前置通知@Before :在目標方法調用之前執行。
後置通知@After:在目標方法調用之後調用,此時不會關係方法的返回是什麼。
返回通知@AfterReturning:在被調用方法成功之後調用。
異常通知@AfterThrowing:在被調用方法異常之後調用。
環繞通知@Around:在包裹了被通知的方法,可以實現以上的所有通知。

3.其他註解介紹
@Aspect :註明這是一個切面
@Pointcut:聲明一個切點
4.切點的限制符
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
5.在spring中使用還需要在配置xml中添加命名空間

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" **xmlns:aop="http://www.springframework.org/schema/aop"**
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
            http://www.springframework.org/schema/beans/spring-beans.xsd 
            http://www.springframework.org/schema/mvc  
            http://www.springframework.org/schema/mvc/spring-mvc.xsd  
            **http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd**
            http://www.springframework.org/schema/context  
            http://www.springframework.org/schema/context/spring-context-3.0.xsd"
    default-lazy-init="true">

**<aop:aspectj-autoproxy proxy-target-class="true" />**

6.使用代碼

package com.xyy.aspect;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AopLog extends LogAspect {
    private Logger logger = LogManager.getLogger(AopLog.class.getName());

    @Pointcut("execution(public * com.xyy.controller.*.*(..))")
    public void recordControllerLog() {
    }

    @Pointcut("execution(public * com.xyy.serviceImpl.*.*(..))")
    public void recordServiceImplLog() {
    }
    @Before("recordControllerLog()")
    public void beforeController() throws Throwable {
    logger.info("-----Controller---begin-----");
    }
    @Around("recordControllerLog()")
    // @Around("execution(* com.xyy.controller.*.*(..))") //execution(* com.xyy.controller.**.*.*(..))<.** 表示controller下面還有包>
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    logger.info("-----打印請求日誌-----");
    return super.logInController(joinPoint);
    }
    @After("recordControllerLog()")
    public void afterController() throws Throwable {
    logger.info("-----Controller---end-----");
    }
    @Before("recordServiceImplLog()")
    public void beforeServiceImpl() throws Throwable {
    logger.info("-----ServiceImpl---begin-----");
    }
    @After("recordServiceImplLog()")
    public void afterServiceImpl() throws Throwable {
    logger.info("-----ServiceImpl---end-----");
    }
}

2.0版本

package com.xyy.springboot.configuration;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * springboot自動開啓aop
 */
@Aspect
@Component
public class BaseLogAspect {
    private static final Logger log = LoggerFactory.getLogger(BaseLogAspect.class);

    /**
     *  execution:用於匹配方法執行的連接點;
     *      *:匹配任何數量字符;
            ..:匹配任何數量字符的重複,如在類型模式中匹配任何數量子包;而在方法參數模式中匹配任何數量參數。
            +:匹配指定類型的子類型;僅能作爲後綴放在類型模式後邊。
                 java.lang.String    匹配String類型;
                 java.*.String       匹配java包下的任何“一級子包”下的String類型;
                 如匹配java.lang.String,但不匹配java.lang.ss.String
                 java..*            匹配java包及任何子包下的任何類型;
                 如匹配java.lang.String、java.lang.annotation.Annotation
                 java.lang.*ing      匹配任何java.lang包下的以ing結尾的類型;
                 java.lang.Number+  匹配java.lang包下的任何Number的自類型;
                 如匹配java.lang.Integer,也匹配java.math.BigInteger
        within:用於匹配指定類型內的方法執行;
        this:用於匹配當前AOP代理對象類型的執行方法;注意是AOP代理對象的類型匹配,這樣就可能包括引入接口也類型匹配;
        target:用於匹配當前目標對象類型的執行方法;注意是目標對象的類型匹配,這樣就不包括引入接口也類型匹配;
        args:用於匹配當前執行的方法傳入的參數爲指定類型的執行方法;
        @within:用於匹配所有持有指定註解類型內的方法;
        @target:用於匹配當前目標對象類型的執行方法,其中目標對象持有指定的註解;
        @args:用於匹配當前執行的方法傳入的參數持有指定註解的執行;
        @annotation:用於匹配當前執行方法持有指定註解的方法;
        bean:Spring AOP擴展的,AspectJ沒有對於指示符,用於匹配特定名稱的Bean對象的執行方法;
        reference pointcut:表示引用其他命名切入點,只有@ApectJ風格支持,Schema風格不支持。
     */
//    只能註釋在方法上
    @Pointcut("@annotation(com.xyy.springboot.configuration.BaseMethodLog)")
//    註釋在類上,使方法都應用
//    @Pointcut("@within(com.xyy.springboot.configuration.BaseTypeLog)")
    public void pointcut(){}

    @Before("pointcut()")
    public void logStart(JoinPoint joinPoint){
        // 方法名稱
        String methodName = joinPoint.getSignature().getName();
        // 方法參數
        Object[] args = joinPoint.getArgs();
        List<Object> list = Arrays.asList(args);
        log.debug(methodName + "方法運行前,參數" + list.toString());
    }

    //如果是別的類調用這個切點,需要寫全類名
    //無論目標方法是否出現異常都會執行
    @After("com.xyy.springboot.configuration.BaseLogAspect.pointcut()")
    public void logEnd(JoinPoint joinPoint){
        // 方法名稱
        String methodName = joinPoint.getSignature().getName();
        log.debug(methodName + "方法運行後");
    }

    @AfterReturning(value = "pointcut()", returning = "result")
    public void logReturn(JoinPoint joinPoint, Object result){
        // 方法名稱
        String methodName = joinPoint.getSignature().getName();
        if (null != result)
            log.debug(methodName + "方法運行結束,結果" + result.toString());
        else
            log.debug(methodName + "方法運行結束");
    }

    @AfterThrowing(value = "pointcut()", throwing = "exception")
    public void logReturn(JoinPoint joinPoint, Exception exception){
        // 方法名稱
        String methodName = joinPoint.getSignature().getName();
        log.debug(methodName + "方法運行異常", exception);
    }

}
發佈了25 篇原創文章 · 獲贊 5 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章