xml配置拦截器
<bean id="operationAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="interceptorNames"> <list><value>recordHistoryInterceptor</value></list> </property> <property name="beanNames"> <list> <value>podUnitMemberService</value> </list> </property> </bean>
<bean id="recordHistoryInterceptor" class="com.umgsai.interceptor.RecordHistoryInterceptor" />
public class RecordHistoryInterceptor implements MethodInterceptor {
@Setter
private HistoryRecorder historyRecorder;
public Object invoke(MethodInvocation invocation) throws Throwable {
Object result = null;
try {
result = invocation.proceed();
} catch (Exception e) {
result = e.getMessage();
throw e;
} finally {
historyRecorder.recordHistory(invocation.getMethod(), invocation.getArguments(), result);
}
return result;
}
}
public void recordHistory(Method method, Object[] params, Object result) throws Throwable {
OperationRecord annotation = method.getAnnotation(OperationRecord.class);
if (annotation != null) {
if (params.length > 0) {
try {
//1. 如果dataType是GLOBAL
if (annotation.dataType() == DataTypeEnum.GLOBAL) {
recordProject(annotation, params, result);
} else {//2. 如果dataType不是GLOBAL,如BASIC,APP_RELATE
recordApp(annotation, method, params, result);
}
} catch (Exception e) {
logger.error("recordHistory error:" + e.getMessage(), e);
}
} else {
logger.warn("含有注解@OperationRecord的方法" + method.getName() + "没有包含参数!");
}
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationRecord {
OperationTypeEnum operationType();
DataTypeEnum dataType();
}
public interface PodUnitMemberService {
//podUnitAppName为podUnitMember类中的属性
@OperationRecord(dataType = DataTypeEnum.BASIC, operationType = OperationTypeEnum.INSERT)
long insert(@IdentifierAnnotation(name = "podUnitAppName") PodUnitMember podUnitMember);
}
private void recordApp(OperationRecord annotation, Method method, Object[] params, Object result)
throws Throwable {
ZappinfoOperationLogDO operationLogDO = new ZappinfoOperationLogDO();
//2.1 设置dataType为注解里的dataType
operationLogDO.setDataType(annotation.dataType().getCode());
//2.2 获取参数注解信息
Annotation[][] paraAnnotationArray = method.getParameterAnnotations();
//2.3 遍历参数注解信息
Object identifier = null;
for (int index = 0; index < paraAnnotationArray.length; index++) {
for (Annotation anno : paraAnnotationArray[index]) {
//2.3.1 如果注解是TargetAnnotation
if (anno instanceof TargetAnnotation) {
//2.3.1.1 appName是从参数中获取
if (((TargetAnnotation) anno).targetSource() == TargetSourceEnum.PARAMETER) {
operationLogDO.setAppName(params[index].toString());
//2.3.1.2 appName是从参数的属性中获取,通过反射调用getAppName方法
} else if (((TargetAnnotation) anno).targetSource() == TargetSourceEnum.ATTRIBUTE) {
operationLogDO.setAppName(params[index].getClass()
.getDeclaredMethod("getAppName").invoke(params[index]).toString());
}
//2.3.2 如果注解是DataTypeAnnotation
} else if (anno instanceof DataTypeAnnotation) {
String dataType = null;
if (((DataTypeAnnotation) anno).dataTypeSource() == DataSourceTypeEnum.CLASS) {
dataType = dataTypeMap.get(params[index].getClass());
} else if (((DataTypeAnnotation) anno).dataTypeSource() == DataSourceTypeEnum.STRING) {
dataType = dataTypeMap.get(params[index]);
}
if (StringUtil.isNotBlank(dataType)) {
operationLogDO.setDataType(dataType);
} else {
logger.warn("没有找到" + params[index].getClass() + "对应的数据类型!");
}
} else if (anno instanceof IdentifierAnnotation) {
//通过IdentifierAnnotation注解获取名称
IdentifierAnnotation idanno = (IdentifierAnnotation) anno;
String name = idanno.name();
identifier = params[index];
if (StringUtil.isNotBlank(name)) {
Object obj = params[index];
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
//去注解中配置的属性名称的值
identifier = field.get(obj);
}
}
}
}
if (identifier == null) {
fillDO(operationLogDO, annotation, params, result);
zappinfoOperationLogDAO.insertOperatinoLog(operationLogDO);
identifier = operationLogDO.getAppName();
}
addOperationRecord(annotation, identifier, method, params, result);
}
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface IdentifierAnnotation {
String name();
}