AOP spring 实例(演示基于注解权限控制及异常处理)

AOP(Aspect-Oriented Programming,面向方面编程),可以说是OOP(Object-OrientedPrograming,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。

spring的支持
Spring中 AOP代理由Spring的 IoC容器负责生成、管理,其依赖关系也由 IoC容器负责管理。因此,AOP代理可以直接使用容器中的其他 Bean实例作为目标,这种关系可由 IoC容器的依赖注入提供。Spring默认使用 Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了。当需要代理的类不是代理接口的时候, Spring自动会切换为使用 CGLIB代理,也可强制使用 CGLIB。

我们程序员需要做的
定义普通业务组件。
定义切入点,一个切入点可能横切多个业务组件。
定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作。
所以进行 AOP编程的关键就是定义切入点和定义增强处理。一旦定义了合适的切入点和增强处理,AOP框架将会自动生成AOP代理,即:代理对象的方法 =增强处理 +被代理对象的方法

直接上代码:

//注解模拟权限校验
@Target({ElementType.METHOD,ElementType.TYPE})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
    String value() default "";
}
/**
 * 简单的定义全局异常处理器 用来捕获异常
 */
@ControllerAdvice
@ResponseBody
public class HandleException {

     //实际开发中Exception类我们需要定义的更加具体  对不同的异常有不同的处理逻辑以及结果返回等
    @ExceptionHandler(Exception.class)
    public String handle(Exception e) {
        System.out.println(" enter  handler  exception ");
        return e.getMessage();
    }
}
/**
 *  这个简单的controller用来演示aop的 
 */
@RestController
@RequestMapping("/demo/user")
public class UserController {

    @GetMapping("/{id}")
    @Auth()
    public String demo1(@PathVariable( "id") String id) {
        System.out.println("  do  somethng ");
        return id;
    }

    @Auth(value = "role")
    @GetMapping("/get")
    public String demo2(String id) {
        //模拟异常
        int i=1/0;
        System.out.println("  do  somethng2 ");
        return id;
    }
}
@Aspect
@Component
@Slf4j
public class AuthAspect {
    /**
     * 定义一个切入点表达式,用来确定哪些类需要代理
     * execution(* com.lq.demo.demo.mode.aop.UserController.*(..)代表UserController下所有方法都会被代理
     */
    @Pointcut("execution(* com.lq.demo.demo.mode.aop.UserController.*(..))")
    public void enhanceMethod() {
    }

    /**
     * 前置方法,在目标方法执行前执行
     *
     * @param joinPoint 封装了代理方法信息的对象,若用不到则可以忽略不写
     */
    @Before("enhanceMethod()")
    public void beforeMethod(JoinPoint joinPoint) {
        String targetMethodName = joinPoint.getSignature().getName();
        log.info("目标方法名:" + targetMethodName);
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        GetMapping annotation = method.getAnnotation(GetMapping.class);
        Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
        Auth auth = method.getAnnotation(Auth.class);
        if(auth==null){
            throw new RuntimeException("no  auth");
        }

        String[] value = annotation.value();
        String[] params = annotation.params();

        for (String s : params) {
            log.info("params:" + s);
        }

        for (String s : value) {
            log.info("annotationvalue:" + s);
        }
        Class<? extends Annotation> annotationType = annotation.annotationType();
        String name = annotation.name();
        Class clazz = joinPoint.getSignature().getDeclaringType();
        log.info("目标方法所属类:" + targetMethodName);
        String type = Modifier.toString(joinPoint.getSignature().getModifiers());
        log.info("目标方法声明类型:" + type);

        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            log.info("第" + (i + 1) + "个参数是:" + (String) args[i]);
        }
        Object target = joinPoint.getTarget();
        log.info("被代理的对象" + target);
        Object aThis = joinPoint.getThis();
        log.info("代理对象自己" + aThis);
        SourceLocation sourceLocation = joinPoint.getSourceLocation();
        log.info("sourceLocation:" + sourceLocation);

        String kind = joinPoint.getKind();
        log.info("kind:" + kind);

    }
    //
    @After("enhanceMethod()")
    public void after() {
        log.info("after");
    }

    @AfterReturning(pointcut = "enhanceMethod()",returning = "rs")
    public void afterReturning(Object rs) {
        log.info("afterreturning"+rs);
    }

    @AfterThrowing(pointcut = "enhanceMethod()",throwing = "e")
    public void afterThrowing(JoinPoint joinPoint,Throwable e) {

        log.info("afterthrowing e:"+e.getMessage() );
    }

    /**
     * 环绕方法,可自定义目标方法执行的时机
     *
     * @param pjd JoinPoint的子接口,添加了
     *            Object proceed() throws Throwable 执行目标方法
     *            Object proceed(Object[] var1) throws Throwable 传入的新的参数去执行目标方法
     *            两个方法
     * @return 此方法需要返回值, 返回值视为目标方法的返回值
     */
    @Around("enhanceMethod()")
    public Object aroundMethod(ProceedingJoinPoint pjd) throws Throwable {
        Object result = null;

        //前置通知
        System.out.println("目标方法执行前...");
        //执行目标方法
        //result = pjd.proeed();
        //用新的参数值执行目标方法
        String o = (String) pjd.getArgs()[0];
        result = pjd.proceed(new Object[]{"newid" + o});
        //返回通知
        System.out.println("目标方法返回结果后...");

        //后置通知
        System.out.println("目标方法执行后...");

        return result;
    }

}

执行结果

这里写图片描述
在@before里我详细的列出来joinpoint’类的使用
通过这个连接点对可以拿到许多我们想要的参数来修改我们的业务代码
在代码中我详细给出了注释
假设我们现在把controller demo方法上的注解@auth去掉 那么通过aop代理我们就实现了权限控制 可以看看结果

 @GetMapping("/{id}")
    public String demo1(@PathVariable( "id") String id) {
        System.out.println("  do  somethng ");
        return id;
    }

再次访问 看结果
这里写图片描述

今天就先spring aop的demo就介绍到这里了。
有问题的朋友可以留言

posted @ 2018-08-18 14:14  pointsl  阅读(237)  评论(0)    收藏  举报