Spring面向切面编程AOP用于拦截器、事务、日志、权限验证等方面。
使用注解方式:
1.先创建个注解类:
/*
* 解释:
* RetentionPolicy(保留策略),分别可以是SOURCE,CLASS,METHOD三种.默认是RetentionPolicy.CLASS.一般设置为RUNTIME运行时,执行得时候加载到虚拟机中。
* Target(指定Annotation类型可以用在哪些元素上,可以是:TYPE,METHOD,FIELD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE等等)
* Documented -- 让这个Annotation类型的信息能够显示在API说明文档上;没有添加的话,使用javadoc生成的API文件找不到这个类型生成的信息
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InterceptTestCode {
String name();
}
2.创建拦截器
/**
* 定义切面
*/
@Aspect
@Component
public class InterceptTestCodeAspect {
private static Logger logger = LoggerFactory.getLogger(InterceptTestCodeAspect.class);
@Autowired
IConfigService configService;
/**
* 设置切入点
* @Pointcut("@annotation(com.tiantai.travel.annotaion.InterceptTestCode)") //表示拦截所有带有InterceptTestCode的注解
* @Pointcut("execution(* com.tiantai.travel..*.*(..))") //表示拦截所有com.tiantai.travel包及子包下的所有的方法
*/
@Pointcut("@annotation(com.tiantai.travel.annotaion.InterceptTestCode)")
public void testCode() {
}
/**
* 设置通知Advice值可以是:
* 前置通知(Before):在目标方法被调用之前调用通知功能
* 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么
* 返回通知(After-returning):在目标方法成功执行之后调用通知
* 异常通知(After-throwing):在目标方法抛出异常后调用通知
* 环绕通知(Around):通知包裹了被通知的方法,在被通知的方
*/
@Around(value = "testCode() && @annotation(code)")
public Object before(ProceedingJoinPoint joinPoint,InterceptTestCode code) throws Throwable {
boolean isIntercept = configService.interceptCode();
if(configService.interceptCode()){
String title = code.name()+"测试拦截不执行方法:"+isIntercept;
logger.info(title);
return "false";
}
Object valueData = joinPoint.proceed();
return valueData;
}
/*
* 例子2
*/
@Around("execution(* com.tiantai.travel.annotaion.*.*(..))")
public Object check(ProceedingJoinPoint pjp) throws Throwable {
Class<?> aClass = pjp.getTarget().getClass(); //先获取被织入增强处理的目标对象,再获取目标类的clazz
String methodName = pjp.getSignature().getName(); //先获取目标方法的签名,再获取目标方法的名
logger.info("methodName: "+methodName); // 输出目标方法名
Class[] parameterTypes = ((MethodSignature) pjp.getSignature()).getParameterTypes(); //获取目标方法参数类型
Object[] args = pjp.getArgs(); //获取目标方法的入参
for (int i = 0; i < args.length; i++) {
logger.info("argsName: "+args[i]); //输出目标方法的参数
}
try {
Method method = aClass.getMethod(methodName, parameterTypes); //获取目标方法
InterceptTestCode annotation = method.getAnnotation(InterceptTestCode.class); //获取方法上的注解
String title = annotation.name(); //获取注解函数值
long starttime = System.currentTimeMillis();
Object proceed = pjp.proceed(); //执行目标方法
long exctime = System.currentTimeMillis() - starttime;
logger.info("执行时间:"+exctime + "毫秒");
logger.info("proceed: "+proceed); //打印目标方法的return结果
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return "aop的返回值";
}
}