在web项目中有很多的AOP是基于路径来拦截的,但是有些情况下项目的API路径是多种多样的,而且需要被拦截做AOP的API也是杂七乱八的,那这种情况下,我们基于包路径的AOP的能力就会觉着很无力。曾经我使用的是黑白名单的功能支持。但是后来发现这种方案代价也挺高的。下面我简单介绍下基于配置注解的AOP拦截,这中实现方案,对我上文讲述的问题的支持能力个人感觉真是太好了。
首先创建一个注解
package org.demo.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface DemoPermission {
String[] demo() default {};
}
基于当前注解实现AOP
package org.demo;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.demo.annotations.DemoPermission;
import org.demo.controller.DemoFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class CopyOfPermissionAspect {
@Autowired(required = false)
DemoFactory demoFactory;
@Before("@annotation(org.demo.annotations.DemoPermission)")
public void before(JoinPoint caller) {
Map<String, Object> functionParamValueMap = getFunctionParamValueMap(caller);
DemoPermission annotation = getAnnotation(caller, DemoPermission.class);
System.out.println("before-->" + annotation);
}
@After("@annotation(org.demo.annotations.DemoPermission)")
public void after(JoinPoint caller) {
DemoPermission annotation = getAnnotation(caller, DemoPermission.class);
System.out.println("after-->" + annotation);
}
@Around("@annotation(org.demo.annotations.DemoPermission)")
public Object around(ProceedingJoinPoint pjp) {
DemoPermission annotation = getAnnotation(pjp, DemoPermission.class);
System.out.println("around-->" + annotation);
Object proceed = null;
try {
proceed = pjp.proceed();
} catch (Throwable e) {
}
return proceed;
}
private <T extends Annotation> T getAnnotation(JoinPoint caller,
Class<T> annotationClass) {
if (caller.getSignature() instanceof MethodSignature) {
MethodSignature methodSignature = (MethodSignature) caller
.getSignature();
return methodSignature.getMethod().getAnnotation(annotationClass);
}
return null;
}
private Map<String, Object> getFunctionParamValueMap(JoinPoint caller) {
Map<String, Object> result = new HashMap<>();
if (caller.getSignature() instanceof MethodSignature) {
Object[] paramsValues = caller.getArgs();
MethodSignature methodSignature = (MethodSignature) caller
.getSignature();
String[] paramNames = methodSignature.getParameterNames();
for (int i = 0, len = paramNames.length; i < len; i++) {
String paramName = paramNames[i];
Object paramValue = paramsValues[i];
result.put(paramName, paramValue);
}
}
return result;
}
}
然后使用注解测试下功能
package org.demo.controller;
import org.demo.annotations.DemoAspect;
import org.demo.annotations.DemoPermission;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@DemoPermission
@RequestMapping("/demo")
public String demo(String name) {
System.out.println("demo--->" + name);
return "demo";
}
}
这个是一个最简单是实现demo,在此基础上我们可以做更多的扩展和支持。详细的扩展代码就不在此一一列出了。
更多代码请访问GitHub