1、注解

  注解英文称 Annotaion,是Java从1.5开始支持加入源码的特殊语法元数据,作为程序的元数据嵌入到程序当中。注解实现有一个重要的接口Annotation接口,利用@interface关键字,将所有使用该关键字的注解类都实现Annotation接口。Annontation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。

2、优点

使用注解的好处:

  1、帮助代码编译检查

  2、提高代码的识别度,比如 @override @Deprecated 

  3、减少重复代码,简化代码

  4、根据注解生成帮助文档,如 @Decument 等

3、元注解

基本语法:

 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 public @interface AnnotationName{
  
 }

元注解就是注解的注解,用来描述注解的。

  • @Retention 定义该注解的生命周期

  1. RetentionPolicy.SOURCE :作用于源码阶段,比如常见的 @Override, @SuppressWarnings;
  2. RetentionPolicy.CLASS :作用于字节码阶段
  3. RetentionPolicy.RUNTIME :作用于运行阶段
  • @Target 定义该注解的作用范围 

  1. ElementType.TYPE :用于注解到类,接口、枚举类
  2. ElementType.FIELD:字段,包括枚举类常量
  3. ElementType.METHOD:方法声明
  4. ElementType.PARAMETER:参数声明
  5. ElementType.CONSTRUCTOR:构造器声明
  6. ElementType.LOCAL_VARIABLE :局部变量声明
  7. ElementType.ANNOTATION_TYPE :用于注解声明,即注解的注解,元注解
  8. ElementType.PACKAGE :包声明
  • 其他注解

  1. @Document 注解将生成到javadoc中
  2. @Deprecated  表示过时的类
  3. @Inherited 是否允许子类继承该注解
  4. @SuppressWarnings 编译器忽略掉无法识别的警告名
  5. @Override 标注的方法重载了父类的方法

 4、自定义注解

import java.lang.annotation.*;

/**
 * 打印出操作日志
 * @author 
 * @create 2019/11/4
 */
//定义该注解的作用范围
@Target({ElementType.TYPE, ElementType.METHOD})
//定义该注解的生命周期
@Retention(RetentionPolicy.RUNTIME)
//注解将生成到javadoc中
@Documented
public @interface SystemLog {
    /**
     * 日志内容
     * @return
     */
    String message() default "";
}

注意:规定注解里面只能使用java基本数据类型和String、enum、Annotation、class

5、自定义注解示例

1> 定义注解接口

import java.lang.annotation.*;

/**
 * 打印出操作日志
 * @author 
 * @create 2019/11/4
 */
//定义该注解的作用范围
@Target({ElementType.TYPE, ElementType.METHOD})
//定义该注解的生命周期
@Retention(RetentionPolicy.RUNTIME)
//注解将生成到javadoc中
@Documented
public @interface SystemLog {
    /**
     * 日志内容
     * @return
     */
    String message() default "";
}

2>实现接口,

import com.example.shiro.config.SystemLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 日志拦截
 * @author 
 * @create 2019/11/4
 */
@Slf4j
//使用order属性,设置该类在spring容器中的加载顺序
@Order(10)
//作用是把当前类标识为一个切面供容器读取
@Aspect
//把普通类实例化到spring容器中
@Component
public class OuterServiceAop {

    @Pointcut("@annotation(com.example.shiro.config.SystemLog)")
    public void serviceAop(){}

    @Before("serviceAop()")
    public void doBefore(JoinPoint joinPoint) {
        log.info("前置通知");
    }

    @After("serviceAop()")
    public void doAfter(JoinPoint joinPoint) {
        log.info("后置通知");
    }

    @AfterReturning(pointcut = "serviceAop()", returning = "res")
    public void doAfterReturning(JoinPoint joinPoint, Object res) {
        log.info("日志返回通知");
        //请求方法
        String method = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        log.info("method:"+ method);

        //日志描述
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method1 = signature.getMethod();
        SystemLog annotation = method1.getAnnotation(SystemLog.class);
        String message = annotation.message();
        log.info(message);
    }

    @AfterThrowing(pointcut = "serviceAop()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
        log.info("异常通知");
        log.info("异常信息:" + e.getMessage());
    }
}

3>在需要的类或方法中增加注解

import com.example.shiro.config.SystemLog;
import com.example.shiro.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;
import com.example.shiro.common.BaseController;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 
 * @since 2019-11-01
 */
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {

    @PostMapping("/login")
    @SystemLog(message = "用户登录")
    public String login(User user) {
        ...
    }
}

4>效果

posted on 2019-11-04 11:29  望~舒  阅读(1012)  评论(0编辑  收藏  举报