註解:
package com.demo.aop;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DimensionPaddingList {
DimensionPadding[] value();
}
package com.demo.aop;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DimensionPadding {
String field();
String fieldAs() default "";
String name();
String nameAs() default "";
Class<?> service() default Object.class;
}
切面實現:
package com.demo.aop;
import com.demo.service.QueryService;
import com.demo.util.AopUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@Component
public class DiamensionPaddingAop extends StaticMethodMatcherPointcutAdvisor implements ApplicationContextAware {
private ApplicationContext applicationContext;
public DiamensionPaddingAop() {
this.setAdvice((MethodInterceptor) (methodInvocation) -> {
Object response;
try {
response = methodInvocation.proceed();
if (response == null) {
return null;
}
Method method = methodInvocation.getMethod();
Object aThis = methodInvocation.getThis();
DimensionPaddingList dimensionPaddingList = AopUtil.findMethodAnnotation(aThis.getClass(), method, DimensionPaddingList.class);
if (dimensionPaddingList != null && dimensionPaddingList.value() != null) {
valueComplement(response, Arrays.asList(dimensionPaddingList.value()));
}
DimensionPadding dimensionPadding = AopUtil.findMethodAnnotation(aThis.getClass(), method, DimensionPadding.class);
if (dimensionPadding != null) {
valueComplement(response, dimensionPadding);
}
} catch (Throwable a) {
throw a;
}
return response;
});
}
private void valueComplement(Object response, List<DimensionPadding> dimensionPaddings) {
dimensionPaddings.forEach(dimensionPadding -> valueComplement(response, dimensionPadding));
}
private void valueComplement(Object response, DimensionPadding dimensionPadding) {
String field = dimensionPadding.field();
String fieldAs = dimensionPadding.fieldAs();
String name = dimensionPadding.name();
String nameAs = dimensionPadding.nameAs();
Class<?> service = dimensionPadding.service();
QueryService queryService = (QueryService) applicationContext.getBean(service);
if (response instanceof Collection) {
Collection dataList = (Collection) response;
for (Object data : dataList) {
Object value = getValue(field, fieldAs, nameAs, queryService, data);
try {
Field declaredField = data.getClass().getDeclaredField(name);
declaredField.setAccessible(true);
if (value instanceof Number) {
declaredField.set(data, (Number) value);
}
if (value instanceof String) {
declaredField.set(data, String.valueOf(value));
}
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
}
}
}
private Object getValue(String field, String fieldAs, String nameAs, QueryService queryService, Object data) {
Field declaredField = null;
try {
declaredField = getDeclaredField(data, field);
assert declaredField != null;
Object o = declaredField.get(data);
Object entity = queryService.findById((Long) o);
Field f = getDeclaredField(entity, nameAs);
assert f != null;
return f.get(entity);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
private Field getDeclaredField(Object obj, String fieldName) {
try {
Field declaredField = obj.getClass().getDeclaredField(fieldName);
if (declaredField != null) {
declaredField.setAccessible(true);
return declaredField;
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return null;
}
@Override
public boolean matches(Method method, Class<?> aClass) {
DimensionPaddingList dimensionPaddingList = AopUtil.findAnnotation(aClass, method, DimensionPaddingList.class);
DimensionPadding dimensionPadding = AopUtil.findAnnotation(aClass, method, DimensionPadding.class);
return dimensionPadding != null || dimensionPaddingList != null;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
使用:
package com.demo.controller;
import com.demo.aop.DimensionPadding;
import com.demo.aop.DimensionPaddingList;
import com.demo.model.TeacherStudentVO;
import com.demo.service.StudentService;
import com.demo.service.TeacherService;
import com.demo.service.TeacherStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping
public class Test {
@Autowired
private TeacherStudentService service;
@RequestMapping("/test")
@DimensionPaddingList({
@DimensionPadding(field = "studentsId", fieldAs = "id", name = "studentName", nameAs = "name", service = StudentService.class)
,
@DimensionPadding(field = "studentTeacherId", fieldAs = "id", name = "teacherName", nameAs = "name", service = TeacherService.class)
,
@DimensionPadding(field = "studentsId", fieldAs = "id", name = "studentAge", nameAs = "age", service = StudentService.class)
,
@DimensionPadding(field = "studentTeacherId", fieldAs = "id", name = "teacherAge", nameAs = "age", service = TeacherService.class)
}
)
public List<TeacherStudentVO> createData() {
return service.getAll();
}
}