admin管理员组

文章数量:1794759

springBoot之自定义注解

springBoot之自定义注解

自定义注解开发:

使用@interface关键字, 其定义过程与定义接口非常类似, 需要注意的是: Annotation的成员变量在Annotation定义中是以无参的方法形式来声明的, 其方法名和返回值类型定义了该成员变量的名字和类型, 而且我们还可以使用default关键字为这个成员变量设定默认值

枚举:

常量的集合,枚举类的实例全部在属性的上面,名字可随便取,但是括号里面的属性必须是下面定义出来的

常用注解

1.@Documented:指定被修饰的该Annotation可以被javadoc工具提取成文档.

2.@Target:指定被修饰的Annotation可以放置的位置(被修饰的目标)

例如:

@Target(ElementType.TYPE)                   接口、类

@Target(ElementType.FIELD)                     属性 @Target(ElementType.METHOD)                方法 @Target(ElementType.PARAMETER)          方法参数 parameter @Target(ElementType.CONSTRUCTOR)     构造函数constructor @Target(ElementType.LOCAL_VARIABLE)   局部变量 @Target(ElementType.ANNOTATION_TYPE)   注解 @Target(ElementType.PACKAGE)                 包 

当一个注解类的@Target()可以为多种位置时,需要在小括号内添加花括号,并且使用逗号隔开

3.@NonNull:属性不为null 

4. @Inherited:指定被修饰的Annotation将具有继承性 

5.@Retention:定义注解的保留策略 有以下三种

 @Retention(RetentionPolicy.SOURCE)             //注解仅存在于源码中,在class字节码文件中不含  @Retention(RetentionPolicy.CLASS)              //默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,  @Retention(RetentionPolicy.RUNTIME)            //注解会在class字节码文件中存在,在运行时可以通过反射获取到

如果 用的是@Retention(RetentionPolicy.CLASS),在TestController类的两个注解只能获取到一个

public class test { public static void main(String[] args) { for (Annotation a : TestController.class.getAnnotations()) { System.out.println(a); } ; } }

 如果 用的是@Retention(RetentionPolicy.RUNTIME),可获取到两个

value为属性,可在注解类中定义其他属性,在赋值时value属性可以不用定义直接引号赋值即可,但是其他的要明确定义

 获取某注解类的属性值时,需要进行判断

如果要判断在某一个类上是否存在某一注解

MyAnnotation annotation = TestController.class.getAnnotation(MyAnnotation.class); if(annotation!=null){ System.out.println(annotation.value()); } 需求:在自定义方法上增加环绕通知

定义一个类,需要的注解:

1.@Aspect:定义切面(需要与@Component一起使用)

2.@Component:定义为组件

3.@Slf4j:日志

在环绕通知的方法上自定义范围

@Pointcut("execution(* com.sjy.controller.*Controller.*(..))")

*表示以 Controller结尾的类的所以方法,可有参也可无参,具体代码如下:

package com.sjy.controller; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; //切面 @Aspect @Component//组件 @Slf4j public class LogAop { @Pointcut("execution(* com.sjy.controller.*Controller.*(..))") public void points(){} @Around("points()") public Object around(ProceedingJoinPoint point){ //获得方法名称 Signature methodName = point.getSignature(); log.info(methodName+"进来了"); long l1 = System.currentTimeMillis(); Object obj=null; try { //执行方法 obj=point.proceed(point.getArgs()); } catch (Throwable throwable) { throwable.printStackTrace(); } log.info(methodName+"出来了-"+(System.currentTimeMillis()-l1)); return obj; } }

但是并不是每个方法都需要被环绕通知的,那就需要不断更改条件,这样是不方便的

我们可以以注解的形式标注在方法上

定义注解类

package com.sjy.annotation; import java.lang.annotation.*; /** * @author 小宝的宝 */ @Documented @Inherited @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyLog { }

在环绕通知的类中给注解类权限

然后只需要在想要环绕的方法上 进行标注注解即可

针对于返回结果的注解及帮助类

1.注解类

package com.sjy.response; import java.lang.annotation.*; /** * @author hgh */ @Retention(value = RetentionPolicy.RUNTIME) @Documented @Target({ElementType.METHOD}) public @interface ResponseResult { }

2.枚举类

package com.sjy.response; import java.io.Serializable; public enum ResultCode implements Serializable { /* 正常状态 */ SUCCESS(100, "成功"), FAILURE(101, "失败"), UNKNOWN(102, "未知响应"), /** * 用户code范围: 200~300; */ USER_ACCOUNT_NOT_FIND(201, "用户名不存在"), USER_ACCOUNT_DISABLED(202, "该用户已被禁用"), USER_PASSWORD_NOT_MATCH(203, "该用户密码不一致"), USER_PERMISSION_ERROR(204, "该用户不具备访问权限"), USER_STATE_OFF_LINE(205, "该用户未登录"); private final Integer code; private final String message; ResultCode(Integer code, String message) { this.code = code; this.message = message; } public Integer getCode() { return code; } public String getMessage() { return message; } public static ResultCode queryCode(Integer code) { for (ResultCode value : values()) { if (code.equals(value.code)) { return value; } } return UNKNOWN; } }

3.帮助类

package com.sjy.response; import lombok.Data; import java.io.Serializable; @Data public class Result<T> implements Serializable { private final int code; private final String message; private final T data; /** * 私有构造, 只允许通过static调用构造 * * @param resultCode 结果枚举 * @param data 响应数据 */ private Result(ResultCode resultCode, T data) { this.code = resultCode.getCode(); this.message = resultCode.getMessage(); this.data = data; } /** * 成功调用返回的结果(无数据携带) * * @return Result */ public static Result success() { return success(null); } /** * 成功调用返回的结果(数据携带) * * @return Result */ public static <T> Result success(T data) { return new Result(ResultCode.SUCCESS, data); } /** * 失败调用返回的结果(数据携带) * * @param resultCode 状态枚举 * @param data 携带的数据 * @return Result */ public static <T> Result failure(ResultCode resultCode, T data) { return new Result(resultCode, data); } /** * 失败调用返回的结果(无数据携带) * * @param resultCode 状态枚举 * @return Result */ public static Result failure(ResultCode resultCode) { return failure(resultCode, null); } }

4.注解解析类

package com.sjy.response; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; @RestControllerAdvice public class ResponseParse implements ResponseBodyAdvice { @Override public boolean supports(MethodParameter methodParameter, Class aClass) { //返回值决定他是否需要进入beforeBodyWrite return methodParameter.getMethod().isAnnotationPresent(ResponseResult.class); } @Override public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { //更改返回值 if (o == null) { return Result.success(); } if (o instanceof Integer) { return Result.failure(ResultCode.queryCode((Integer) o)); } if (o instanceof ResultCode) { return Result.failure((ResultCode) o); } if (o instanceof Result) { return o; } return null; } }

本文标签: 自定义注解SpringBoot