springboot中兩種方式配置切面

在工作中做項目微服務化,需要把原來老的項目拆分成一個個小的接口對外提供服務。對拆分出來的接口,需要做權限控制與入參,出參,耗時等日誌記錄。於是做個了切面類,來通過切面對相應方法做記錄。

1.首先我們需要引入相應的jar包
 

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

 

 

 

 

2.找一個你需要做切面攔截的接口

例如我想對下圖中的testProxy()方法做切面攔截,記錄日誌信息:

package com.example.demo.service.impl;

import java.util.Date;

import org.springframework.stereotype.Service;

@Servicepublic class TestAspectServiceImpl {
    public String testAspect(String str) {
        System.out.println("========" + new Date().getTime() + "===========");
        return str + "yes";
    }
}

 

 

 

 

 

 

2.1.1接着開始寫切面類

在這裏我們對需要控制的接口做了出參和入參進行日誌記錄:

package com.example.demo.aspect;

import java.util.Arrays;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TestAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger( TestAspect.class );
    @Around( value = "(execution(* com.example.demo.service.impl..*.*(..)))" )
    public Object service( ProceedingJoinPoint joinPoint ) {
        String method = joinPoint.getTarget().getClass().getSimpleName() + "." + joinPoint.getSignature().getName() + "(..)";
        // 調用接口方法
        Object response = null;
        try {
            LOGGER.info( "Service start. method : {} , Param : {}", method, Arrays.toString(joinPoint.getArgs()) );
            response = joinPoint.proceed();
            LOGGER.info( "Service finish. method : {}, Result : {}", method, response );
        } catch( Throwable e ) {
            LOGGER.error( "Service error. method : {} , Cause : {}", method, e );
        } finally {
            //ThreadContext.serialDestroy();
        }
        return response;
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

execution(* com.example.demo.service.impl..*.*(..))

execution()是最常用的切點函數,其語法如下所示: 整個表達式可以分爲五個部分:

 1、execution(): 表達式主體。

 2、第一個*號:表示返回類型,*號表示所有的類型。

 3、包名:表示需要攔截的包名,後面的兩個句點表示當前包和當前包的所有子包,com.example.demo.service.impl包、子孫包下所有類的方法。

 4、第二個*號:表示類名,*號表示所有的類。

 5、*(..):最後這個星號表示方法名,*號表示所有的方法,後面括弧裏面表示方法的參數,兩個句點表示任何參數。

 

2.1.2編寫測試類

@Test
    public void ProxyServiceImplTest() {
        testAspectServiceImpl.testAspect("isAspect?");
    }

 

 

 

 

單元測試結果爲,可以看到切面打印了入參與出參:

com.example.demo.aspect.TestAspect       : Service start. method : TestAspectServiceImpl.testAspect(..) , Param : [isAspect?]
========1552894755581===========
com.example.demo.aspect.TestAspect       : Service finish. method : TestAspectServiceImpl.testAspect(..), Result : isAspect?yes

 

 

 

這裏是直接根據描述的路徑去找到想要增加切面的方法,如果我們想個性化,可以通過在方法上增加標籤,即可實現對該方法的切面工作。

2.2.1自定義標籤

package com.example.demo.annotation;

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

//聲明註解的保留期限
@Retention(RetentionPolicy.RUNTIME)
//聲明可以使用該註解的目標類型
@Target(ElementType.METHOD)
@Documented
public @interface Authority {
    // 聲明註解成員
    boolean value() default false;
}

 

 

 

 

 

 

 

 

 

2.2.2標籤切面

@Aspect
@Component
public class AuthorityAspect {
    @Around( value = "@annotation(com.example.demo.annotation.Authority)" )
    public Object service(ProceedingJoinPoint joinPoint ){
        Object[] args = joinPoint.getArgs();
        if("y".equals(args[0])) {
            try {
                joinPoint.proceed();
            } catch (Throwable e) {
                e.printStackTrace();
            }
            return "yes";
        }
        return "no";
    }


}

 

 

 

 

 

 

 

 

 

 

 

在你所有添加切面的接口中加上註解就可以了

@Service
public class TestAspectServiceImpl {
    @Authority
    public String testAspect(String str) {
        System.out.println("========" + new Date().getTime() + "===========");
        return str + "yes";
    }
}

 

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