這幾天工作的時候遇到這樣一個需求,需要以用戶的維度對列表展示的內容實現可自定義配置列功能,並且后端返回的值沒有冗余值。由於系統之前並沒有此設計,需要短期實現又不想大動代碼,功能基本實現;但是在后台返回列表數據沒有冗余的時候發現基本每個返回列表的接口都需要有所修改,而且都是一些重復的修改,所以就想到通過AOP使前置增強后置增強,在通過注解的方式告知哪些方法需要增強,並通過注解的方式傳參;因此此處簡單記錄下實現過程以及具體的代碼邏輯;
步驟1:創建Spring boot項目
此步驟此處就不在贅述;
步驟2:
2.1由於此處使用了Springboot的aop功能,所以maven需要引入AOP的依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2.2 定義自定義注解
@Target(ElementType.METHOD) //定義是用在方法上 @Retention(RetentionPolicy.RUNTIME) // 定義是在運行時生效 public @interface ZlTest { String param() default ""; //定義參數,默認為空 }
步驟3:定義切面
3.1先上代碼
package com.zl.demo.aspect; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.zl.concurrency.annoations.ZlTest; import com.zl.demo.unit.SpelParser; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.stereotype.Component; import java.lang.reflect.Method; /** * 定義一個切面,用於統計指定注解的方法調用時間 * * @author zl * @ProjectName: MapDemo * @create 2018-12-13 10:08 * @Version: 1.0 * <p>Copyright: Copyright (zl) 2018</p> **/ @Component @Aspect @Slf4j public class ZlAspect { @Around("serviceStatistics(zlTest)") public Object doAround(ProceedingJoinPoint joinPoint, ZlTest zlTest) throws Throwable { System.out.println("beginning----"); /** * 獲取方法參數值 */ String key = getKey(zlTest.param(), joinPoint); log.info("參數是:{}",key); /** * 運行doSth(),執行方法的具體業務,並獲取返回值,用一個Object類型來接收 */ Object object = joinPoint.proceed(); /** * 該方法的后置增強,可以修改返回值 */ object = 10; return object; } private String getKey(String param, ProceedingJoinPoint joinPoint) { Method method = ((MethodSignature)joinPoint.getSignature()).getMethod(); //獲取方法的形參 String [] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(method); return SpelParser.getKey(param, "", parameterNames, joinPoint.getArgs()); } }
3.2 此處使用的是環繞增強
@Around注解,后面加上具體需要掃描的方法,這里是掃描我們自定義注解的方法
doAround方法的兩個參數:ProceedingJoinPoint:是指具體的切面點,通過該對象可以獲取到切面點的所有的方法,方法的屬性,方法的形參;ZlTest指的就是我們自定的注解,通過這里可以獲取到注解的參數值信息;
3.3 getKey()方法
getkey方法是我們自定義的一個方法,主要是通過EL表達式獲取到方法的形參,此處不再贅述,可以查看 https://www.aliyun.com/jiaocheng/529697.html一文,此處只是根據注解的參數和方法的參數信息獲取到方法的指定參數的值;
步驟4:定義我們需要注解的方法
package com.zl.demo.controller;
@Slf4j @Controller @RequestMapping("threadLocal") public class ThreadLocalController { @Autowired private Validator validator; @RequestMapping("test") @ResponseBody @ZlTest(param = "#id") public long test(String id, String name){ return RequestHolder.getId(); } }
這里通過#id占位,獲取方法的id參數的值
步驟5:執行結果如下
這里通過Object獲取到方法的返回值,可以修改該返回值
步驟6:demo代碼git地址
git@github.com:zlAdmin/didactic-enigma.git
注意:項目中有本人寫的其他測試demo,請注意該demo的路徑;