<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          JAVA注解那些事

          共 4698字,需瀏覽 10分鐘

           ·

          2023-06-07 01:30

          45d1c4ad636ba0d3d2936d7d38ef0047.webp

          一、概念

          Annotation(注解) 是 Java 提供的一種對(duì)元程序中元素關(guān)聯(lián)信息和元數(shù)據(jù)(metadata)的途徑和方法。

          Annatation(注解)是一個(gè)接口,程序可以通過(guò) 反射 來(lái)獲取指定程序中元素的 Annotation對(duì)象,然后通過(guò)該Annotation 對(duì)象來(lái)獲取注解中的元數(shù)據(jù)信息。

          二、 4 種標(biāo)準(zhǔn)元注解

          元注解 的作用是負(fù)責(zé)注解其他注解。Java5.0 定義了 4 個(gè)標(biāo)準(zhǔn)的 meta-annotation 類型,它們被用來(lái)提供對(duì)其它 annotation 類型作說(shuō)明。

          1、@Target 修飾的對(duì)象范圍

          @Target說(shuō)明了Annotation所修飾的對(duì)象范圍:Annotation可被用于 packages、types(類、接口、枚舉、Annotation 類型)、類型成員(方法、構(gòu)造方法、成員變量、枚舉值)、方法參數(shù)和本地變量(如循環(huán)變量、catch 參數(shù))。在 Annotation 類型的聲明中使用了 target 可更加明晰其修飾的目標(biāo)

          2、@Retention 定義被保留的時(shí)間長(zhǎng)短

          Retention 定義了該 Annotation 被保留的時(shí)間長(zhǎng)短:表示需要在什么級(jí)別保存注解信息,用于描述注解的生命周期(即:被描述的注解在什么范圍內(nèi)有效),取值(RetentionPoicy)由:

          • SOURCE:在源文件中有效(即源文件保留)

          • CLASS:在 class 文件中有效(即 class 保留)

          • RUNTIME:在運(yùn)行時(shí)有效(即運(yùn)行時(shí)保留)

          3、@Documented 描述-javadoc

          @ Documented 用于描述其它類型的 annotation 應(yīng)該被作為被標(biāo)注的程序成員的公共 API,因此可以被例如 javadoc 此類的工具文檔化。

          4、@Inherited 闡述了某個(gè)被標(biāo)注的類型是被繼承的

          @Inherited 元注解是一個(gè)標(biāo)記注解,@Inherited 闡述了某個(gè)被標(biāo)注的類型是被繼承的。如果一個(gè)使用了@Inherited 修飾的 annotation 類型被用于一個(gè) class,則這個(gè) annotation 將被用于該class 的子類。
          215a77cddee9a3d84ac0b1ba78b57257.webp

          三、(自定義注解)注解處理器

          Java 的基本注解和元注解,如果這兩種注解不能滿足你的需求,可以自定義注解。Java SE5 擴(kuò)展了反射機(jī)制的 API,以幫助程序員快速的構(gòu)造自定義注解處理器。默認(rèn)情況下,注解可以在程序的任何地方使用,通常用于修飾類、接口、方法和變量等。

          下面實(shí)現(xiàn)一個(gè)注解處理器(自定義注解)。

          1、定義注解

          使用 @interface 關(guān)鍵字聲明自定義注解:

          不包含任何成員變量的注解稱為 標(biāo)記注解 ,基本注解中的 @Override 注解都屬于標(biāo)記注解。

              
                // 定義一個(gè)簡(jiǎn)單的注解類型
          public @interface Test {
          }

          根據(jù)需要,注解中可以定義成員變量,成員變量以無(wú)形參的方法形式來(lái)聲明,成員變量也可以有訪問(wèn)權(quán)限修飾符,但是只能有公有權(quán)限和默認(rèn)權(quán)限。

              
                import java.lang.annotation.*;
          @Retention(RetentionPolicy.RUNTIME)
          @Target({ElementType.METHOD})
          @Documented
          public @interface UvLogAnnotation {
          // 定義帶成員變量的注解。注解中的成員變量也可以有默認(rèn)值,可使用 default 關(guān)鍵字。
          // 注解中的成員變量以方法的形式來(lái)定義,其方法名和返回值定義了該成員變量的名字和類型
          String methodKey() default "";
          }

          根據(jù)注解是否包含成員變量,可以分為如下兩類:
          1、標(biāo)記注解:沒(méi)有定義成員變量的注解類型被稱為標(biāo)記注解。這種注解僅利用自身的存在與否來(lái)提供信息,如前面介紹的 @Override、@Test 等都是標(biāo)記注解。
          2、元數(shù)據(jù)注解:包含成員變量的注解,因?yàn)樗鼈兛梢越邮芨嗟脑獢?shù)據(jù),所以也被稱為元數(shù)據(jù)注解。

          2、Aspect切面類處理

              
                /**
          * 瀏覽量統(tǒng)計(jì)
          */

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

          // 拿到@UVlog注解注釋的方法,這里就是切點(diǎn)
          @Pointcut("@annotation(com.aop.annotation.UvLogAnnotation)")
          private void serviceAspect() {

          }

          // 調(diào)用方法后都會(huì)進(jìn)行統(tǒng)計(jì)操作,寫入redis
          @After("serviceAspect()")
          public void afterMethod(JoinPoint joinPoint) {
          log.info("開(kāi)始統(tǒng)計(jì)處理:**************");
          MethodSignature sign = (MethodSignature) joinPoint.getSignature();
          Method method = sign.getMethod();
          // 獲取指定注解實(shí)例
          UvLogAnnotation annotation = method.getAnnotation(UvLogAnnotation.class);
          String methodKey = annotation.methodKey();
          String[] argNames = sign.getParameterNames();
          List<String> argNameList = Arrays.asList(argNames);
          Map<String, Object> paramsMap = new HashMap<>();
          //處理參數(shù)(將參數(shù)或者對(duì)象屬性值統(tǒng)一放到paramsMap中)
          resolveArgs(joinPoint, argNameList, paramsMap);
          log.info("開(kāi)始記錄redis:{}", JSONObject.toJSONString(paramsMap));
          try {
          saveToRedis(methodKey, paramsMap);
          } catch (Exception e) {
          log.info("redis 異常,降級(jí)處理!");
          }
          }

          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<String> argNameList,
          Map<String, Object> paramsMap) {
          Object[] argObjects = joinPoint.getArgs(); // 參數(shù)對(duì)象集合
          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(p));
          }
          });
          }
          }

          public static <T> T get(Class<T> 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 = "統(tǒng)計(jì)用戶流量次數(shù)")
          public class UserController {

          @Autowired
          private UserInfoService userInfoService;
          @Autowired
          private RedisService redisService;

          @ApiOperation(value = "統(tǒng)計(jì)用戶流量次數(shù)")
          @GetMapping(value = "/user/count")
          // 使用帶成員變量的注解時(shí),需要為成員變量賦值
          @UvLogAnnotation(methodKey = "USER_COUNT")
          public Result<Integer> 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);
          }

          4f7fe1659914c70c8db1766d466fa821.webp

          瀏覽 63
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  东方AV在线一 | gogo高清无码视频 | 人人澡人人妻人人爽人人蜜桃 | 黄色一级aa片 | 日韩五码在线 |