2018-10-18

Spring boot 学习之aop使用及自定义注解

严格来说,这算是笔者作为程序员的第一篇博客笔记。最近公司项目比较忙,不过刚入职不到一月的我,还可以忙里偷闲浪一下。废话不多说,下面进入正题。
Spring boot 号称“简化新Spring应用的搭建及开发”的高端集成式框架,用来开发项目相比传统的框架来说,简直不能太爽。今天工作之余,我尝试自己搭建了一个springboot的demo,使用自定义注解实现配置aop。
创建一个springboot项目,需要引入的依赖:

org.springframework.boot
  spring-boot-starter-aop


org.springframework.boot
  spring-boot-starter-web

之后创建一个测试用的controller,

@RestController
public class TestController {
    @GetMapping("/test/{name}")
    @LogAnnotation
    public String getUser(@PathVariable String name){
        return name;
    }
}

先跑一下项目,保证能够正常运行,在前端能够获取到返回值name
接下来自定义一个注解类,在aop配置类里面要用到。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
}

然后创建aop配置类,类上面需要注解@Aspect @Component,然后依然是 where when what,代码如下:

@Aspect
@Component
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
public class TestAspect {
    @Autowired
    private LoginfoService loginfoService;

    //where when,贴有LogAnnotation注解的Controller方法打印日志
    @Pointcut(("execution(* cn.aop.demo.web..*.*(..)) && @annotation(cn.aop.demo.anno.LogAnnotation)"))
    public void logAdvice(){}
    //what,使用aop到底要做什么增强
    @Around("logAdvice()")
    public Object doLogAdvice(ProceedingJoinPoint pjp){
        Object result = null;
        Signature signature = pjp.getSignature();
        if (!(signature instanceof MethodSignature)) {
            throw new IllegalArgumentException("读写注解只能作用于方法");
        }

        loginfoService.printLog();
        try {
            result = pjp.proceed();
        }catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return result;
    }
}

这里的ProceedingJoinPoint对象一定不要忘记调用方法proceed(),否则程序就会卡在这里,不在往下执行。
这时候只要在对象的controller方法中,贴上我们指定的注解,然后访问该控制器,就会触发aop切面增强,调用我们设置好的业务方法。
另外,关于aop配置类上面的注解,@EnableAspectJAutoProxy,这里简单介绍一下两个参数,一个是控制aop的具体实现方式,为true 的话使用cglib,为false的话使用java的Proxy,默认为false,第二个参数控制代理的暴露方式,解决内部调用不能使用代理的场景,默认为false. 源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

    /**
     * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
     * to standard Java interface-based proxies. The default is {@code false}.
     */
    boolean proxyTargetClass() default false;

    /**
     * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
     * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
     * Off by default, i.e. no guarantees that {@code AopContext} access will work.
     * @since 4.3.1
     */
    boolean exposeProxy() default false;

}

你可能感兴趣的:(2018-10-18)