您好,登錄后才能下訂單哦!
這篇文章跟大家分析一下“springboot注解Aspect的實現方案是什么”。內容詳細易懂,對“springboot注解Aspect的實現方案是什么”感興趣的朋友可以跟著小編的思路慢慢深入來閱讀一下,希望閱讀后能夠對大家有所幫助。下面跟著小編一起深入學習“springboot注解Aspect的實現方案是什么”的知識吧。
下面提供一種自定義注解,來實現業務審批操作的DEMO,不包含審批流程的配置功能。
具體方案是
自定義一個Aspect注解,攔截sevice方法,將攔截的信息持久化,待審批;審批時獲取持久化數據,執行目標方法。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.8</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.proc</groupId> <artifactId>process-test</artifactId> <version>1.0.0-SNAPSHOT</version> <name>process-test</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <!-- 用于主線程給子線程傳遞數據,支持線程池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>transmittable-thread-local</artifactId> <version>2.12.2</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
用于包裝頁面傳進來的參數
package com.proc.model; import java.util.List; public class CheckedParam { //業務標記,由頁面傳入,用于審批時頁面根據tagPageJs解析data,渲染到頁面,審批管理員可看到審批的內容 private String tagPageJs; //頁面傳入的原始數據 private List<String> data; public String getTagPageJs() { return tagPageJs; } public void setTagPageJs(String tagPageJs) { this.tagPageJs = tagPageJs; } public List<String> getData() { return data; } public void setData(List<String> data) { this.data = data; } }
攔截的信息包裝類,用于持久化數據
package com.proc.model; public class ProcessDbModel { //bean的目標類全限定名 private String targetClassName; //攔截到的service方法名 private String methodName; //頁面傳入的tagPageJs或Checked注解的tag private String tag; private String description; //攔截到的service入參類型,包含泛型信息 private String paramTypes; //攔截到的service入參值 private String paramArgs; //攔截到的service入參值或頁面傳入的原始數據 private String data; public String getTargetClassName() { return targetClassName; } public void setTargetClassName(String targetClassName) { this.targetClassName = targetClassName; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public String getTag() { return tag; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public void setTag(String tag) { this.tag = tag; } public String getParamTypes() { return paramTypes; } public void setParamTypes(String paramTypes) { this.paramTypes = paramTypes; } public String getParamArgs() { return paramArgs; } public void setParamArgs(String paramArgs) { this.paramArgs = paramArgs; } public String getData() { return data; } public void setData(String data) { this.data = data; } @Override public String toString() { return "ProcessDbModel [targetClassName=" + targetClassName + ", methodName=" + methodName + ", tag=" + tag + ", description=" + description + ", paramTypes=" + paramTypes + ", paramArgs=" + paramArgs + ", data=" + data + "]"; } }
package com.proc.model; import java.math.BigDecimal; public class Score { private BigDecimal langue; private BigDecimal math; private BigDecimal english; public BigDecimal getLangue() { return langue; } public void setLangue(BigDecimal langue) { this.langue = langue; } public BigDecimal getMath() { return math; } public void setMath(BigDecimal math) { this.math = math; } public BigDecimal getEnglish() { return english; } public void setEnglish(BigDecimal english) { this.english = english; } @Override public String toString() { return "Score [langue=" + langue + ", math=" + math + ", english=" + english + "]"; } }
package com.proc.model; import java.util.List; public class Person<T> { private String name; private String age; private String sex; private String testName; private String salary; private String work; private List<T> grades; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getSalary() { return salary; } public void setSalary(String salary) { this.salary = salary; } public String getTestName() { return testName; } public void setTestName(String testName) { this.testName = testName; } public String getWork() { return work; } public void setWork(String work) { this.work = work; } public List<T> getGrades() { return grades; } public void setGrades(List<T> grades) { this.grades = grades; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", sex=" + sex + ", testName=" + testName + ", salary=" + salary + ", work=" + work + ", grades=" + grades + "]"; } }
JacksonCanonicalUtil
package com.proc.util; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.json.JsonMapper; public class JacksonCanonicalUtil { private static final JsonMapper MAPPER = new JsonMapper(); private JacksonCanonicalUtil () {} public static <T> String toCanonical (Class<T> clazz) { return MAPPER.getTypeFactory().constructType(clazz).toCanonical(); } public static <T> String toCanonical (TypeReference<T> tr) { return MAPPER.getTypeFactory().constructType(tr).toCanonical(); } //反序列化時從持久數據中獲取JavaType public static JavaType constructFromCanonical (String canonical) { return MAPPER.getTypeFactory().constructFromCanonical(canonical); } }
StringZipUtil
用于壓縮和解壓字符串,減少持久數據占用空間
package com.proc.util; import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterOutputStream; public class StringZipUtil { private StringZipUtil () {} public static String zipBase64(String text) { try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { try (OutputStream os = new DeflaterOutputStream(out)) { os.write(text.getBytes(StandardCharsets.UTF_8)); } return Base64.getEncoder().encodeToString(out.toByteArray()); } catch (Exception e) { throw new RuntimeException("壓縮字符串出錯", e); } } public static String unzipBase64(String text) { try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { try (OutputStream os = new InflaterOutputStream(out)) { os.write(Base64.getDecoder().decode(text)); } return new String(out.toByteArray(), StandardCharsets.UTF_8); } catch (Exception e) { throw new RuntimeException("解壓字符串出錯", e); } } }
一些參數值轉為Base64后持久化
package com.proc.util; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Base64; import java.util.List; import java.util.stream.Collectors; import com.fasterxml.jackson.databind.json.JsonMapper; public class Base64Util { private Base64Util () {} private static final JsonMapper MAPPER = new JsonMapper(); public static String[] toStrings (Object[] objs) { List<String> list = new ArrayList<>(); try { for (Object obj : objs) { list.add(MAPPER.writeValueAsString(obj)); } } catch (Exception e) { throw new RuntimeException("序列化對象出錯", e); } return list.toArray(new String[0]); } public static String encode (String[] strs) { List<String> list = new ArrayList<>(); for (String str : strs) { list.add(Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); } String join = list.stream().collect(Collectors.joining("|")); return join; } public static String[] decode (String text) { String[] strs = text.split("\\|", -1); List<String> list = new ArrayList<>(); for (String base64 : strs) { list.add(new String(Base64.getDecoder().decode(base64), StandardCharsets.UTF_8)); } return list.toArray(new String[0]); } public static String encodeZip (Object[] objs) { return encodeZip(toStrings(objs)); } public static String encodeZip (String[] strs) { List<String> list = new ArrayList<>(); for (String str : strs) { list.add(StringZipUtil.zipBase64(str)); } String join = list.stream().collect(Collectors.joining("|")); return StringZipUtil.zipBase64(join); } public static String[] decodeZip (String text) { String str = StringZipUtil.unzipBase64(text); String[] strs = str.split("\\|", -1); List<String> list = new ArrayList<>(); for (String base64 : strs) { list.add(StringZipUtil.unzipBase64(base64)); } return list.toArray(new String[0]); } }
package com.proc.util; import java.util.Map; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class SpringBootBeanUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringBootBeanUtil.applicationContext = applicationContext; } public static ApplicationContext getApplicationContext() { return applicationContext; } public static Object getBean(String name) { return applicationContext.getBean(name); } public static <T> T getBean(Class<T> clazz) { return (T) applicationContext.getBean(clazz); } public static <T> T getBean(String name, Class<T> clazz) { return applicationContext.getBean(name, clazz); } public static <T> Map<String, T> getBeansOfType(Class<T> clazz) { return applicationContext.getBeansOfType(clazz); } }
用于執行目標方法
package com.proc.util; import java.lang.reflect.Method; import org.springframework.util.ReflectionUtils; public class ProcessBeanUtil { private ProcessBeanUtil () {} public static Object excuteBeanMethod (String targetClassName, String methodName, Class<?>[] parameterTypes, Object[] args) { Class<?> targetClass; try { targetClass = Class.forName(targetClassName); } catch (ClassNotFoundException e) { throw new RuntimeException("未找到類", e); } return excuteBeanMethod(targetClass, methodName, parameterTypes, args); } public static Object excuteBeanMethod (Class<?> targetClass, String methodName, Class<?>[] parameterTypes, Object[] args) { Object bean = SpringBootBeanUtil.getBean(targetClass); Method method = ReflectionUtils.findMethod(targetClass, methodName, parameterTypes); return ReflectionUtils.invokeMethod(method, bean, args); } }
用于傳遞業務參數
package com.proc.util; import com.alibaba.ttl.TransmittableThreadLocal; import com.proc.model.CheckedParam; public class CheckedTransmitableUtil { private static final TransmittableThreadLocal<CheckedParam> threadLocal = new TransmittableThreadLocal<>(); private CheckedTransmitableUtil () {} public static void set (CheckedParam checkedParam) { threadLocal.set(checkedParam); } public static CheckedParam getAndRemove () { CheckedParam checkedParam = threadLocal.get(); threadLocal.remove(); return checkedParam; } }
為Aspect判斷是否攔截提供依據
package com.proc.util; import com.alibaba.ttl.TransmittableThreadLocal; public class PrivateTransmitableUtil { private static final String CHECKED = "__CHECKED__"; private static final TransmittableThreadLocal<String> threadLocal = new TransmittableThreadLocal<>(); private PrivateTransmitableUtil () {} public static void set () { threadLocal.set(CHECKED); } //是否執行的審批程序 public static boolean isCheck () { String checked = threadLocal.get(); threadLocal.remove(); return CHECKED.equals(checked); } }
用于攔截方法后做的個性處理
package com.proc.bean; public interface PostProcess<T> { //返回說明內容,審批時在頁面顯示 String description(String tag, Class<?>[] parameterTypes, Object[] args); //返回代替的返回值 T retObject(String tag, Class<?>[] parameterTypes, Object[] args); }
測試用
package com.proc.bean; import org.springframework.stereotype.Component; @Component public class TestCheckPostProcess implements PostProcess<String> { @Override public String description(String tag, Class<?>[] parameterTypes, Object[] args) { return tag + "測試testCheck"; } @Override public String retObject(String tag, Class<?>[] parameterTypes, Object[] args) { return tag + "返回攔截響應"; } }
package com.proc.config; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; import com.proc.bean.PostProcess; @Retention(RUNTIME) @Target(METHOD) public @interface Checked { String tag() default ""; /** * @see com.proc.util.JacksonCanonicalUtil * @return */ String[] paramCanonical(); Class<? extends PostProcess<?>> postProcess(); }
package com.proc.config; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.proc.bean.PostProcess; import com.proc.model.CheckedParam; import com.proc.model.ProcessDbModel; import com.proc.service.ProcessDbService; import com.proc.util.Base64Util; import com.proc.util.CheckedTransmitableUtil; import com.proc.util.PrivateTransmitableUtil; import com.proc.util.SpringBootBeanUtil; @Component @Aspect public class CheckedAop { @Autowired private ProcessDbService processDbService; //攔截Checked注釋的方法 @Pointcut("@annotation(com.proc.config.Checked)") public void check() { } @Around(value = "com.proc.config.CheckedAop.check() && @annotation(checked)") public Object around(ProceedingJoinPoint joinPoint, Checked checked) throws Throwable { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Class<?>[] parameterTypes = signature.getParameterTypes(); String methodName = signature.getMethod().getName(); Object[] args = joinPoint.getArgs(); if (PrivateTransmitableUtil.isCheck()) { //審批后,執行業務代碼 Object returnVal = joinPoint.proceed(); return returnVal; } else { //不是審批操作,攔截 Class<? extends PostProcess<?>> postProcess = checked.postProcess(); PostProcess<?> bean = SpringBootBeanUtil.getBean(postProcess); //組裝持久化數據 ProcessDbModel dbModel = new ProcessDbModel(); dbModel.setTargetClassName(joinPoint.getTarget().getClass().getName()); dbModel.setMethodName(methodName); String tag = checked.tag(); CheckedParam checkedParam = CheckedTransmitableUtil.getAndRemove(); if (checkedParam == null || checkedParam.getTagPageJs() == null || checkedParam.getTagPageJs().isEmpty()) { //不是頁面調用的業務,使用注解的tag,data保存為service的參數,這時需要頁面專門解析渲染 String[] argStrs = Base64Util.toStrings(args); dbModel.setParamArgs(Base64Util.encodeZip(argStrs)); dbModel.setData(Base64Util.encode(argStrs)); } else { tag = checkedParam.getTagPageJs(); dbModel.setParamArgs(Base64Util.encodeZip(args)); dbModel.setData(Base64Util.encode(checkedParam.getData().toArray(new String[0]))); } dbModel.setTag(tag); dbModel.setParamTypes(Base64Util.encodeZip(checked.paramCanonical())); dbModel.setDescription(bean.description(tag, parameterTypes, args)); //持久化數據 processDbService.save(dbModel); return bean.retObject(tag, parameterTypes, args); } } }
測試用
package com.proc.config; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import com.alibaba.ttl.threadpool.TtlExecutors; @Configuration public class TaskExecutePoolConfig { @Bean public Executor processExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //核心線程池大小 executor.setCorePoolSize(10); //最大線程數 executor.setMaxPoolSize(10); //隊列容量 executor.setQueueCapacity(500); //活躍時間 executor.setKeepAliveSeconds(60); //線程名字前綴 executor.setThreadNamePrefix("ProcessExecutor-"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); // 等待所有任務結束后再關閉線程池 executor.setWaitForTasksToCompleteOnShutdown(true); executor.initialize(); //用transmittable-thread-local包裝,才可以正確給線程池中的線程傳遞數據 return TtlExecutors.getTtlExecutor(executor); } }
為測試方便,未真正實現持久化
package com.proc.service; import com.proc.model.ProcessDbModel; public interface ProcessDbService { void save (ProcessDbModel model); ProcessDbModel get (); }
package com.proc.service.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import com.proc.model.ProcessDbModel; import com.proc.service.ProcessDbService; @Component public class ProcessDbServiceImpl implements ProcessDbService { private static final Logger log = LoggerFactory.getLogger(ProcessDbService.class); private volatile ProcessDbModel model; @Override public void save(ProcessDbModel model) { this.model = model; log.info(model.toString()); } @Override public ProcessDbModel get() { return this.model; } }
package com.proc.service; import com.proc.model.ProcessDbModel; public interface ProcessCheckService { void process (ProcessDbModel model); }
package com.proc.service.impl; import java.util.ArrayList; import java.util.List; import java.util.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.json.JsonMapper; import com.proc.model.ProcessDbModel; import com.proc.service.ProcessCheckService; import com.proc.util.Base64Util; import com.proc.util.JacksonCanonicalUtil; import com.proc.util.PrivateTransmitableUtil; import com.proc.util.ProcessBeanUtil; @Service public class ProcessCheckServiceImpl implements ProcessCheckService { private static final Logger log = LoggerFactory.getLogger(ProcessCheckServiceImpl.class); private static final JsonMapper MAPPER = new JsonMapper(); @Override public void process(ProcessDbModel model) { PrivateTransmitableUtil.set(); String[] paramArgs = Base64Util.decodeZip(model.getParamArgs()); String[] paramTypes = Base64Util.decodeZip(model.getParamTypes()); List<Class<?>> parameterTypes = new ArrayList<>(); List<Object> args = new ArrayList<>(); try { for (int i = 0; i < paramTypes.length; i++) { JavaType javaType = JacksonCanonicalUtil.constructFromCanonical(paramTypes[i]); parameterTypes.add(javaType.getRawClass()); args.add(MAPPER.readValue(paramArgs[i], javaType)); } } catch (JsonProcessingException e) { throw new RuntimeException("反序列化對象出錯", e); } Object ret = ProcessBeanUtil.excuteBeanMethod( model.getTargetClassName(), model.getMethodName(), parameterTypes.toArray(new Class<?>[0]), args.toArray(new Object[0]) ); log.info(Objects.toString(ret)); } }
package com.proc.service; import com.proc.model.Person; import com.proc.model.Score; public interface TestService { String testCheck(Person<Score> person, String team); String testCheck2(Person<Score> person, String team); String testCheckAsync(Person<Score> person, String team); }
package com.proc.service.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import com.proc.bean.TestCheckPostProcess; import com.proc.config.Checked; import com.proc.model.Person; import com.proc.model.Score; import com.proc.service.TestService; @Service public class TestServiceImpl implements TestService { private static final Logger log = LoggerFactory.getLogger(TestServiceImpl.class); //paramCanonical對應testCheck的參數類型 @Checked( paramCanonical = {"com.proc.model.Person<com.proc.model.Score>", "java.lang.String"}, postProcess = TestCheckPostProcess.class) @Override public String testCheck(Person<Score> person, String team) { log.info(team + ">>>>" + person); return "target方法"; } @Checked( tag = "A1", paramCanonical = {"com.proc.model.Person<com.proc.model.Score>", "java.lang.String"}, postProcess = TestCheckPostProcess.class) @Override public String testCheck2(Person<Score> person, String team) { log.info(team + ">>2>>" + person); return "target2方法"; } @Async("processExecutor") @Checked( paramCanonical = {"com.proc.model.Person<com.proc.model.Score>", "java.lang.String"}, postProcess = TestCheckPostProcess.class) @Override public String testCheckAsync(Person<Score> person, String team) { log.info(team + ">>>>" + person); return "target方法"; } }
package com.proc.ctrl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.proc.model.ProcessDbModel; import com.proc.service.ProcessCheckService; import com.proc.service.ProcessDbService; @RestController public class ProcessCheckController { private static final Logger log = LoggerFactory.getLogger(ProcessCheckController.class); @Autowired private ProcessDbService processDbService; @Autowired private ProcessCheckService processCheckService; @GetMapping(value = "process") public String process() { ProcessDbModel processDbModel = processDbService.get(); log.info(processDbModel.toString()); processCheckService.process(processDbModel); return "審批成功"; } }
package com.proc.ctrl; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.proc.model.CheckedParam; import com.proc.model.Person; import com.proc.model.Score; import com.proc.service.TestService; import com.proc.util.CheckedTransmitableUtil; @RestController public class TestController { @Autowired private TestService testService; //模擬頁面調用 @GetMapping(value = "index") public String testCheck() { CheckedParam checkedParam = new CheckedParam(); checkedParam.setTagPageJs("01"); List<String> data = new ArrayList<>(); data.add("前端傳進來的數據1"); data.add("前端傳進來的數據2"); checkedParam.setData(data); CheckedTransmitableUtil.set(checkedParam); Person<Score> person = new Person<>(); person.setName("一個人"); person.setAge("18"); person.setSex("1"); person.setSalary("20000.00"); person.setTestName("測試人"); person.setWork("工作"); Score score1 = new Score(); score1.setEnglish(new BigDecimal("12.4")); score1.setLangue(new BigDecimal("764")); score1.setMath(new BigDecimal("87.4")); Score score2 = new Score(); score2.setEnglish(new BigDecimal("12.4")); score2.setLangue(new BigDecimal("764")); score2.setMath(new BigDecimal("87.4")); List<Score> list = new ArrayList<>(); list.add(score1); list.add(score2); person.setGrades(list); testService.testCheck(person, "team>>>>>>>>"); return "12345"; } //模擬其他渠道調用 @GetMapping(value = "index2") public String testCheck2() { Person<Score> person = new Person<>(); person.setName("一個人"); person.setAge("18"); person.setSex("1"); person.setSalary("20000.00"); person.setTestName("測試人"); person.setWork("工作"); Score score1 = new Score(); score1.setEnglish(new BigDecimal("12.4")); score1.setLangue(new BigDecimal("764")); score1.setMath(new BigDecimal("87.4")); Score score2 = new Score(); score2.setEnglish(new BigDecimal("12.4")); score2.setLangue(new BigDecimal("764")); score2.setMath(new BigDecimal("87.4")); List<Score> list = new ArrayList<>(); list.add(score1); list.add(score2); person.setGrades(list); testService.testCheck2(person, "team>>>2>>>>>"); return "12345"; } //模擬調用異步方法 @GetMapping(value = "index3") public String testCheckAsync() { CheckedParam checkedParam = new CheckedParam(); checkedParam.setTagPageJs("01"); List<String> data = new ArrayList<>(); data.add("前端傳進來的數據1"); data.add("前端傳進來的數據2"); checkedParam.setData(data); CheckedTransmitableUtil.set(checkedParam); Person<Score> person = new Person<>(); person.setName("一個人"); person.setAge("18"); person.setSex("1"); person.setSalary("20000.00"); person.setTestName("測試人"); person.setWork("工作"); Score score1 = new Score(); score1.setEnglish(new BigDecimal("12.4")); score1.setLangue(new BigDecimal("764")); score1.setMath(new BigDecimal("87.4")); Score score2 = new Score(); score2.setEnglish(new BigDecimal("12.4")); score2.setLangue(new BigDecimal("764")); score2.setMath(new BigDecimal("87.4")); List<Score> list = new ArrayList<>(); list.add(score1); list.add(score2); person.setGrades(list); testService.testCheckAsync(person, "team>>>3>>>>>"); return "12345"; } }
package com.proc; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication @EnableAsync public class ProcessTestApplication { public static void main(String[] args) { SpringApplication.run(ProcessTestApplication.class, args); } }
關于springboot注解Aspect的實現方案是什么就分享到這里啦,希望上述內容能夠讓大家有所提升。如果想要學習更多知識,請大家多多留意小編的更新。謝謝大家關注一下億速云網站!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。