注解简单来说就是配置,是特别的配置,之前常用的配置文件,可以用注解替换。然后通过反射去获取注解的信息。

如何定义一个注解

你在IDE中新建一个注解定义,是这样的结构的:

  1. package com.nicchagil.exercise.springbootexercise.annotation;
  2. public @interface MyFirstAnnotation {
  3. }

然后大概有4个对上述结构加上一些配置,当然,这配置是以注解的形式添加的=_=!

此注解使用在哪里

此注解会应用的哪里,可通过如下配置:

保留在什么时候

保留到什么时候:

注解体现在文档中

@Documented

子类是否继承父类的注解

@Inherited

用反射获取注解的信息

我们先定义一个注解:

  1. package com.nicchagil.exercise.springbootexercise.annotation;
  2. import java.lang.annotation.Documented;
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7. @Target(ElementType.METHOD)
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Documented
  10. public @interface PojoPostProcessing {
  11. public Class targetClass();
  12. public String[] whiteProperties();
  13. }

使用注解,比如这里我设置到一个方法上:

  1. @PojoPostProcessing(targetClass=User.class, whiteProperties={"name"})
  2. public List<User> selectXxx(String id) {
  3. ......
  4. }

反射获取注解的信息:

  1. @Test
  2. public void test() throws NoSuchMethodException, SecurityException, ClassNotFoundException {
  3. Class clazz = Class.forName("com.nicchagil.exercise.springbootexercise.service.UserService");
  4. Method method = clazz.getMethod("selectXxx", String.class);
  5. boolean isAnnotationPresent = method.isAnnotationPresent(PojoPostProcessing.class);
  6. if (!isAnnotationPresent) {
  7. return;
  8. }
  9. PojoPostProcessing dpp = (PojoPostProcessing)method.getAnnotation(PojoPostProcessing.class);
  10. this.logger.info("dpp : {}", dpp);
  11. }

日志:

  1. dpp : @com.nicchagil.exercise.springbootexercise.annotation.PojoPostProcessing(targetClass=class com.nicchagil.exercise.springbootexercise.mapper.entity.User, whiteProperties=[name])

在Spring AOP中解析注解,然后实体你注解需要做的业务

比如以下就是在Spring AOP中拦截到方法,通过JoinPoint获取反射的Method,然后看是否有指定注解,如果有注解,后面就是关于此注解要做的业务逻辑了:

  1. package com.nicchagil.exercise.springbootexercise.aop;
  2. import java.lang.reflect.Method;
  3. import org.aspectj.lang.JoinPoint;
  4. import org.aspectj.lang.Signature;
  5. import org.aspectj.lang.annotation.AfterReturning;
  6. import org.aspectj.lang.annotation.Aspect;
  7. import org.aspectj.lang.annotation.Pointcut;
  8. import org.aspectj.lang.reflect.MethodSignature;
  9. import org.slf4j.Logger;
  10. import org.slf4j.LoggerFactory;
  11. import org.springframework.context.annotation.Configuration;
  12. import com.nicchagil.exercise.springbootexercise.annotation.PojoPostProcessing;
  13. @Aspect
  14. @Configuration
  15. public class ServiceControllerLogAop {
  16. private Logger logger = LoggerFactory.getLogger(this.getClass());
  17. @Pointcut("execution(* com.nicchagil.exercise.springbootexercise.service.*Service.*(..))")
  18. public void myPointcut() {
  19. }
  20. @AfterReturning("myPointcut()")
  21. public void myBefore(JoinPoint joinPoint) {
  22. /* 获取方法对象 */
  23. Signature signature = joinPoint.getSignature();
  24. if (signature == null && !(signature instanceof MethodSignature)) {
  25. return;
  26. }
  27. MethodSignature methodSignature = (MethodSignature)signature;
  28. Method method = methodSignature.getMethod();
  29. /* 是否有指定注解 */
  30. boolean isAnnotationPresent = method.isAnnotationPresent(PojoPostProcessing.class);
  31. if (!isAnnotationPresent) {
  32. return;
  33. }
  34. /* 获取注解信息 */
  35. PojoPostProcessing dpp = (PojoPostProcessing)method.getAnnotation(PojoPostProcessing.class);
  36. this.logger.info("dpp : {}", dpp);
  37. }
  38. }

过滤注解方法的返回值的指定属性

将属性置空的工具类:

  1. package com.nicchagil.exercise.springbootexercise.util;
  2. import java.beans.PropertyDescriptor;
  3. import java.lang.reflect.InvocationTargetException;
  4. import java.lang.reflect.Method;
  5. import java.util.ArrayList;
  6. import java.util.Arrays;
  7. import java.util.HashSet;
  8. import java.util.List;
  9. import java.util.Set;
  10. import org.slf4j.Logger;
  11. import org.slf4j.LoggerFactory;
  12. import org.springframework.beans.BeanUtils;
  13. import org.springframework.core.MethodParameter;
  14. public class BeanClearUtils {
  15. private static Logger logger = LoggerFactory.getLogger(BeanClearUtils.class);
  16. public static void clearProperty(Object obj, String[] whiteProperty) {
  17. List<PropertyDescriptor> clearList = BeanClearUtils.getClearProperty(obj.getClass(), whiteProperty);
  18. try {
  19. for (PropertyDescriptor pd : clearList) {
  20. MethodParameter mp = BeanUtils.getWriteMethodParameter(pd);
  21. Method method = mp.getMethod();
  22. method.invoke(obj, new Object[] {null});
  23. }
  24. } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
  25. throw new RuntimeException("设置空属性失败", e);
  26. }
  27. }
  28. /**
  29. * 获取需要清除的字段列表
  30. */
  31. public static List<PropertyDescriptor> getClearProperty(Class<?> clazz, String[] whiteProperty) {
  32. PropertyDescriptor[] allPropertyDescriptor = BeanUtils.getPropertyDescriptors(clazz);
  33. /* 需保留的字段 */
  34. Set<String> whitePropertySet = new HashSet<String>(Arrays.asList(whiteProperty));
  35. whitePropertySet.add("class"); // 此字段无须清除
  36. /* 需清除的字段 */
  37. List<PropertyDescriptor> clearList = new ArrayList<PropertyDescriptor>();
  38. for (PropertyDescriptor propertyDescriptor : allPropertyDescriptor) {
  39. if (!whitePropertySet.contains(propertyDescriptor.getName())) {
  40. clearList.add(propertyDescriptor);
  41. }
  42. }
  43. return clearList;
  44. }
  45. }

定义注解:

  1. package com.nicchagil.exercise.springbootexercise.annotation;
  2. import java.lang.annotation.Documented;
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7. @Target(ElementType.METHOD)
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Documented
  10. public @interface PojoPostProcessing {
  11. public String[] whiteProperties();
  12. }

处理注解逻辑:

  1. package com.nicchagil.exercise.springbootexercise.aop;
  2. import java.lang.reflect.Method;
  3. import org.aspectj.lang.JoinPoint;
  4. import org.aspectj.lang.Signature;
  5. import org.aspectj.lang.annotation.AfterReturning;
  6. import org.aspectj.lang.annotation.Aspect;
  7. import org.aspectj.lang.annotation.Pointcut;
  8. import org.aspectj.lang.reflect.MethodSignature;
  9. import org.slf4j.Logger;
  10. import org.slf4j.LoggerFactory;
  11. import org.springframework.context.annotation.Configuration;
  12. import com.nicchagil.exercise.springbootexercise.annotation.PojoPostProcessing;
  13. import com.nicchagil.exercise.springbootexercise.util.BeanClearUtils;
  14. @Aspect
  15. @Configuration
  16. public class BeanPropertyFilterAop {
  17. private Logger logger = LoggerFactory.getLogger(this.getClass());
  18. @Pointcut("execution(* com.nicchagil.exercise.springbootexercise.service.*Service.*(..))")
  19. public void myPojoPostProcessingPointcut() {
  20. }
  21. @AfterReturning(value = "myPojoPostProcessingPointcut()", returning = "returnObject")
  22. public void myAfter(JoinPoint joinPoint, Object returnObject) {
  23. /* 获取方法对象 */
  24. Signature signature = joinPoint.getSignature();
  25. if (signature == null && !(signature instanceof MethodSignature)) {
  26. return;
  27. }
  28. MethodSignature methodSignature = (MethodSignature) signature;
  29. Method method = methodSignature.getMethod();
  30. /* 是否有指定注解 */
  31. boolean isAnnotationPresent = method.isAnnotationPresent(PojoPostProcessing.class);
  32. if (!isAnnotationPresent) {
  33. return;
  34. }
  35. /* 获取注解信息 */
  36. PojoPostProcessing dpp = (PojoPostProcessing) method.getAnnotation(PojoPostProcessing.class);
  37. this.logger.info("dpp : {}", dpp);
  38. /* 只保留bean的指定属性值(其它属性值置空) */
  39. logger.info("before bean : {}", returnObject);
  40. BeanClearUtils.clearProperty(returnObject, dpp.whiteProperties());
  41. logger.info("after bean : {}", returnObject);
  42. }
  43. }

使用注解:

  1. @PojoPostProcessing(whiteProperties={"name", "createTime"})

【Java基础】Java注解简单入门的更多相关文章

  1. Java基础-Java中23种设计模式之常用的设计模式

    Java基础-Java中23种设计模式之常用的设计模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.设计模式分类 设计模式是针对特定场景给出的专家级的解决方案.总的来说设 ...

  2. Java基础-Java数据类型

    Java基础-Java数据类型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数据类型的作用 数据类型就是一组值,以及这一组值上的操作,数据类型可以决定数据的存储方式,取值范围 ...

  3. java基础---->java中正则表达式二

    跟正则表达式相关的类有:Pattern.Matcher和String.今天我们就开始Java中正则表达式的学习. Pattern和Matcher的理解 一.正则表达式的使用方法 一般推荐使用的方式如下 ...

  4. Java基础-Java中的堆内存和离堆内存机制

    Java基础-Java中的堆内存和离堆内存机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  5. Java基础-Java中的内存分配与回收机制

    Java基础-Java中的内存分配与回收机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一. 二.

  6. Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock)

    Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在学习Java的之前,你可能已经听说过读 ...

  7. Java基础-Java中的并法库之线程池技术

    Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.

  8. Java基础-JAVA中常见的数据结构介绍

    Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...

  9. 【转载】JAVA基础:注解

    原文:https://www.cnblogs.com/xdp-gacl/p/3622275.html#undefined 一.认识注解 注解(Annotation)很重要,未来的开发模式都是基于注解的 ...

随机推荐

  1. Linux 默认目录

    /etc 存放系统管理所需要的配置文件和子目录 /home 一般用户的主目录 /usr 用户使用的系统目录和应用程序等信息 /bin  存放使用者经常使用的命令 如cp  ls cat 等 /proc ...

  2. C# GridViewExportUtil

    using System.Data; using System.IO; using System.Web; using System.Web.UI; using System.Web.UI.WebCo ...

  3. Xamarin Essentials应用教程文件系统FileSystem

    Xamarin Essentials应用教程文件系统FileSystem 文件系统用于管理设备内的各类文件.通过文件系统,应用程序可以创建永久文件和临时文件,也可以获取预先打包的文件,如预设数据库文件 ...

  4. 在notepad++中修改换行符

    在notepad++中编辑时,将按tab键设置为插入4个空格而不是tab字符

  5. spark实时计算性能优化

    1.  计算提供两种模式,一种是jar包本地计算.一种是JSF服务. 2.  第一步是引入spark,因与netty.JDQ均有冲突,解决netty冲突后,隔离计算为单独服务.已在线上,因storm也 ...

  6. bzoj3033: 太鼓达人 欧拉路径

    题目链接 bzoj3033: 太鼓达人 题解 对于k-1位点,k位二进制位边,将点的转移连起来 每个点的入度和出度相等并且全部是偶点 只需要在这个图中找字典序最小的欧拉回路 可以贪心地找字典序较小的边 ...

  7. java发送邮件高级篇

    package com.xiets.javamaildemo; import java.util.Date; import java.util.Properties; import javax.act ...

  8. Lua的 table.sort排序

    在用table.sort 排序的时候注意,如果使用多个条件排序,应在一个排序函数里按照条件优先级进行比较排序. 例如 local t = { {time = , i = }, {time = , i ...

  9. 潭州课堂25班:Ph201805201 爬虫高级 第八课 AP抓包 SCRAPY 的图片处理 (课堂笔记)

    装好模拟器设置代理到 Fiddler  中, 代理 IP 是本机 IP, 端口是 8888, 抓包 APP斗鱼 用 format 设置翻页

  10. 简单酷炫的Canvas数字时钟

    声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢! 我记得很早之前就看过这个DEMO,是岑安大大博客里看到的: 就是这个数字时钟,当时觉得这个创意不错,但是也没去折腾.直到昨天同事又在网上看 ...