天天看點

Spring boot 自定義注解+AOPAOP面向切面程式設計

AOP面向切面程式設計

AOP(Aspect Oriented Programming)面向切面程式設計,一種程式設計範式,指導開發者如何組織程式結構。

作用:在不驚動原始設計的基礎上為其進行功能增強,前面咱們有技術就可以實作這樣的功能即代理模式。

有以下幾個概念:

1.通知(Advice)——給目标方法添加額外操作稱之為通知,也可以稱為增強

2.連接配接點(Joinpoint)——就是可以增強的地方(方法的前後某個階段)

3.切入點(Pointcut)——實際增強的地方

4.切面(Aspect)——封裝了通知和切入點用來橫向插入的類

5.代理(Proxy)——将通知應用到目标類動态建立的對象

6.織入(Weaving)——将切面插入到目标進而生成代理對象的過程

當我們了解了相關概念之後結合代碼看看

/**
 * AOP切面統計閱讀量
 */
@Aspect
@Component
public class ReadingNumAspect {


    private final IPersonalCenterService personalCenterService;
    private final RedisUtil redisUtil;

    public ReadingNumAspect(IPersonalCenterService articleService, RedisUtil redisUtil) {
        this.personalCenterService = articleService;
        this.redisUtil = redisUtil;
    }

    //Controller層切入點,這裡用到了自定義注解的形式,下面會介紹
    @Pointcut("@annotation(tech.niua.core.annotation.ReadingNum)")
    private void ControllerAspet(){
    }

    /**
     * 後置通知,統計閱讀量
     * @param joinPoint
     */
    @After("ControllerAspet()")
    private void doBefore(JoinPoint joinPoint){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //請求url
        System.out.println("------------url:"+request.getRequestURI());
        //調用的方法
        System.out.println("------------method:"+joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()");
        String[] strs=request.getRequestURI().split("/");
        System.out.println(strs[3]);
        this.personalCenterService.readingVolumeIncrease(Long.valueOf(strs[3]));
        //請求的參數
        Map<String, String[]> properties = request.getParameterMap();
        Map<Object, Object> returnMap = new HashMap<Object, Object>();
        Iterator<Map.Entry<String, String[]>> entries = properties.entrySet().iterator();
        Map.Entry entry;
        String name = "";
        String value = "";

        while (entries.hasNext()) {
            entry = (Map.Entry) entries.next();
            name = (String) entry.getKey();
            Object valueObj = entry.getValue();
            if (null == valueObj) {
                value = "";
            } else if (valueObj instanceof String[]) {
                String[] values = (String[]) valueObj;
                for (int i = 0; i < values.length; i++) {
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length() - 1);
            } else {
                value = valueObj.toString();
            }
            returnMap.put(name, value);
        }
        System.out.println("------------param:"+returnMap.toString());

    }
}
           

接下來我們再來看一定義注解:

import java.lang.annotation.*;

/**
 * controller層閱讀量攔截
 *
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ReadingNum {
    String value() default "";
}
           

首次,我們建立一個注解檔案

然後,我們在相應的方法上使用該注解

/**
     * 根據id查詢文章
     */
    @ReadingNum()
    @PostMapping("/student/{id}")
    public ResultJson student(@PathVariable Long id) {
       //業務代碼
    }
           

然後,我們利用切面,将切入點改成該注解,就實作了,自定義注解的切面

繼續閱讀