JAVA元注解、自定义注解

一、概念

Annotation(注解)是 Java 提供的一种对元程序中元素关联信息和元数据(metadata)的途径和方法。

Annatation(注解)是一个接口,程序可以通过反射来获取指定程序中元素的 Annotation对象,然后通过该Annotation 对象来获取注解中的元数据信息。

二、 5 种元注解

1. @Retention注解指定了标记的注解如何存储:

RetentionPolicy.SOURCE,标记的注解仅保留在源代码级别,并被编译器忽略。
RetentionPolicy.CLASS,标记的注解在编译时由编译器保留,但被Java虚拟机(JVM)忽略。
RetentionPolicy.RUNTIME,标记的注解由JVM保留,以便运行时环境可以使用。

2. @Documented注解指示每当使用指定的注解时,应使用Javadoc工具记录这些元素。

3. @Target注解标记了另一个注解,以限制该注解可以应用于哪种Java元素。@Target注解指定以下元素类型之一作为其值:

ElementType.ANNOTATION_TYPE,可以应用于注解类型。
ElementType.CONSTRUCTOR,可以应用于构造函数。
ElementType.FIELD,可以应用于字段或属性。
ElementType.LOCAL_VARIABLE,可以应用于局部变量。
ElementType.METHOD,可以应用于方法级注解。
ElementType.PACKAGE,可以应用于包声明。
ElementType.PARAMETER,可以应用于方法的参数。
ElementType.TYPE,可以应用于类的任何元素。

4. @Inherited注解表示该注解类型可以从超类继承(默认情况下并非如此)。当用户查询注解类型并且该类没有该类型的注解时,将查询该类的超类以获取注解类型。此注解仅适用于类声明。

5. @Repeatable注解是JavaSE8中引入的,表示标记的注解可以多次应用于同一声明或类型使用。

三、(自定义注解)注解处理器

Java 的基本注解和元注解,如果这两种注解不能满足你的需求,可以自定义注解。Java SE5 扩展了反射机制的 API,以帮助程序员快速的构造自定义注解处理器。默认情况下,注解可以在程序的任何地方使用,通常用于修饰类、接口、方法和变量等。

下面实现一个注解处理器(自定义注解)。

1、定义注解

使用 @interface 关键字声明自定义注解:

不包含任何成员变量的注解称为标记注解,基本注解中的 @Override 注解都属于标记注解。

// 定义一个简单的注解类型
public @interface Test {
}

根据需要,注解中可以定义成员变量,成员变量以无形参的方法形式来声明,成员变量也可以有访问权限修饰符,但是只能有公有权限和默认权限。

import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface UvLogAnnotation {
// 定义带成员变量的注解。注解中的成员变量也可以有默认值,可使用 default 关键字。
// 注解中的成员变量以方法的形式来定义,其方法名和返回值定义了该成员变量的名字和类型
String methodKey() default “”;
}

根据注解是否包含成员变量,可以分为如下两类:
1、标记注解:没有定义成员变量的注解类型被称为标记注解。这种注解仅利用自身的存在与否来提供信息,如前面介绍的 @Override、@Test 等都是标记注解。
2、元数据注解:包含成员变量的注解,因为它们可以接受更多的元数据,所以也被称为元数据注解。

2、Aspect切面类处理

@Aspect
@Component
@Slf4j
public class UvLogAspect {
@Autowired
private RedisService redisService;
@Autowired
private UserLogService userLogService;


// 拿到@UVlog注解注释的方法,这里就是切点
@Pointcut(“@annotation(com.aop.annotation.UvLogAnnotation)”)
private void serviceAspect() {
}


// 调用方法后都会进行统计操作,写入redis
@After(“serviceAspect()”)
public void afterMethod(JoinPoint joinPoint) {
log.info(“开始统计处理:**************”);
MethodSignature sign = (MethodSignature) joinPoint.getSignature();
Method method = sign.getMethod();
// 获取指定注解实例
UvLogAnnotation annotation = method.getAnnotation(UvLogAnnotation.class);
String methodKey = annotation.methodKey();
String[] argNames = sign.getParameterNames();
List argNameList = Arrays.asList(argNames);
Map<String, Object> paramsMap = new HashMap<>();
//处理参数(将参数或者对象属性值统一放到paramsMap中)
resolveArgs(joinPoint, argNameList, paramsMap);
log.info(“开始记录redis:{}”, JSONObject.toJSONString(paramsMap));
try {
saveToRedis(methodKey, paramsMap);
} catch (Exception e) {
log.info(“redis 异常,降级处理!”);
}
}


public void saveToRedis(String methodKey, Map<String, Object> paramsMap) {
if (UvLogKeyEnum.DCZS_COUNT.getValue().equals(methodKey)) {
userLogService.saveToRedis(methodKey, paramsMap);
}
}


public static void resolveArgs(JoinPoint joinPoint, List argNameList,
Map<String, Object> paramsMap) {
Object[] argObjects = joinPoint.getArgs(); // 参数对象集合
for (int i = 0; i < argNameList.size(); i++) {
Class<?> classo = argObjects[i].getClass();
if (handleClassType(classo.getName())) {
paramsMap.put(argNameList.get(i), joinPoint.getArgs()[i]);
continue;
}
JSONObject object = (JSONObject) JSONObject.toJSON(joinPoint.getArgs()[i]);
object.keySet().parallelStream().forEach(p -> {
if (!p.equals(“grantedAuthorities”)) {
paramsMap.put(p, object.get§);
}
});
}
}


public static T get(Class clz, Object o) {
if (clz.isInstance(o)) {
return clz.cast(o);
}
return null;
}


public static boolean handleClassType(String name) {
AtomicBoolean result = new AtomicBoolean(false);
String[] className = {“String”, “Integer”, “Long”, “int”, “float”, “double”, “char”};
Arrays.asList(className).forEach(n -> {
if (name.contains(n)) {
result.set(name.contains(n));
}
});
return result.get();
}

3、注解的使用

Controller中使用自定义注解@UvLogAnnotation:

@RestController
@RequestMapping(“/api”)
@Slf4j
@Api(tags = “统计用户流量次数”)
public class UserController {
@Autowired
private UserInfoService userInfoService;
@Autowired
private RedisService redisService;


@ApiOperation(value = “统计用户流量次数”)
@GetMapping(value = “/user/count”)
// 使用带成员变量的注解时,需要为成员变量赋值
@UvLogAnnotation(methodKey = “USER_COUNT”)
public Result countUserViews(@ApiIgnore OauthUser user) {
if (user == null) {
return Result.error(BasicCodeMsg.AUTHORIZATION_ERROR);
}
user.setGmtCreate(new Date());
Integer result = userInfoService.countUserViews(user);
return Result.success(result);
}

  • 26
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值