【Java基础】Java注解简单入门
注解简单来说就是配置,是特别的配置,之前常用的配置文件,可以用注解替换。然后通过反射去获取注解的信息。
如何定义一个注解
你在IDE中新建一个注解定义,是这样的结构的:
package com.nicchagil.exercise.springbootexercise.annotation;
public @interface MyFirstAnnotation {
}
然后大概有4个对上述结构加上一些配置,当然,这配置是以注解的形式添加的=_=!
此注解使用在哪里
此注解会应用的哪里,可通过如下配置:

保留在什么时候
保留到什么时候:

注解体现在文档中
@Documented
子类是否继承父类的注解
@Inherited
用反射获取注解的信息
我们先定义一个注解:
package com.nicchagil.exercise.springbootexercise.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PojoPostProcessing {
public Class targetClass();
public String[] whiteProperties();
}
使用注解,比如这里我设置到一个方法上:
@PojoPostProcessing(targetClass=User.class, whiteProperties={"name"})
public List<User> selectXxx(String id) {
......
}
反射获取注解的信息:
@Test
public void test() throws NoSuchMethodException, SecurityException, ClassNotFoundException {
Class clazz = Class.forName("com.nicchagil.exercise.springbootexercise.service.UserService");
Method method = clazz.getMethod("selectXxx", String.class);
boolean isAnnotationPresent = method.isAnnotationPresent(PojoPostProcessing.class);
if (!isAnnotationPresent) {
return;
}
PojoPostProcessing dpp = (PojoPostProcessing)method.getAnnotation(PojoPostProcessing.class);
this.logger.info("dpp : {}", dpp);
}
日志:
dpp : @com.nicchagil.exercise.springbootexercise.annotation.PojoPostProcessing(targetClass=class com.nicchagil.exercise.springbootexercise.mapper.entity.User, whiteProperties=[name])
在Spring AOP中解析注解,然后实体你注解需要做的业务
比如以下就是在Spring AOP中拦截到方法,通过JoinPoint获取反射的Method,然后看是否有指定注解,如果有注解,后面就是关于此注解要做的业务逻辑了:
package com.nicchagil.exercise.springbootexercise.aop;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import com.nicchagil.exercise.springbootexercise.annotation.PojoPostProcessing;
@Aspect
@Configuration
public class ServiceControllerLogAop {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Pointcut("execution(* com.nicchagil.exercise.springbootexercise.service.*Service.*(..))")
public void myPointcut() {
}
@AfterReturning("myPointcut()")
public void myBefore(JoinPoint joinPoint) {
/* 获取方法对象 */
Signature signature = joinPoint.getSignature();
if (signature == null && !(signature instanceof MethodSignature)) {
return;
}
MethodSignature methodSignature = (MethodSignature)signature;
Method method = methodSignature.getMethod();
/* 是否有指定注解 */
boolean isAnnotationPresent = method.isAnnotationPresent(PojoPostProcessing.class);
if (!isAnnotationPresent) {
return;
}
/* 获取注解信息 */
PojoPostProcessing dpp = (PojoPostProcessing)method.getAnnotation(PojoPostProcessing.class);
this.logger.info("dpp : {}", dpp);
}
}
过滤注解方法的返回值的指定属性
将属性置空的工具类:
package com.nicchagil.exercise.springbootexercise.util;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.core.MethodParameter;
public class BeanClearUtils {
private static Logger logger = LoggerFactory.getLogger(BeanClearUtils.class);
public static void clearProperty(Object obj, String[] whiteProperty) {
List<PropertyDescriptor> clearList = BeanClearUtils.getClearProperty(obj.getClass(), whiteProperty);
try {
for (PropertyDescriptor pd : clearList) {
MethodParameter mp = BeanUtils.getWriteMethodParameter(pd);
Method method = mp.getMethod();
method.invoke(obj, new Object[] {null});
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException("设置空属性失败", e);
}
}
/**
* 获取需要清除的字段列表
*/
public static List<PropertyDescriptor> getClearProperty(Class<?> clazz, String[] whiteProperty) {
PropertyDescriptor[] allPropertyDescriptor = BeanUtils.getPropertyDescriptors(clazz);
/* 需保留的字段 */
Set<String> whitePropertySet = new HashSet<String>(Arrays.asList(whiteProperty));
whitePropertySet.add("class"); // 此字段无须清除
/* 需清除的字段 */
List<PropertyDescriptor> clearList = new ArrayList<PropertyDescriptor>();
for (PropertyDescriptor propertyDescriptor : allPropertyDescriptor) {
if (!whitePropertySet.contains(propertyDescriptor.getName())) {
clearList.add(propertyDescriptor);
}
}
return clearList;
}
}
定义注解:
package com.nicchagil.exercise.springbootexercise.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PojoPostProcessing {
public String[] whiteProperties();
}
处理注解逻辑:
package com.nicchagil.exercise.springbootexercise.aop;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import com.nicchagil.exercise.springbootexercise.annotation.PojoPostProcessing;
import com.nicchagil.exercise.springbootexercise.util.BeanClearUtils;
@Aspect
@Configuration
public class BeanPropertyFilterAop {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Pointcut("execution(* com.nicchagil.exercise.springbootexercise.service.*Service.*(..))")
public void myPojoPostProcessingPointcut() {
}
@AfterReturning(value = "myPojoPostProcessingPointcut()", returning = "returnObject")
public void myAfter(JoinPoint joinPoint, Object returnObject) {
/* 获取方法对象 */
Signature signature = joinPoint.getSignature();
if (signature == null && !(signature instanceof MethodSignature)) {
return;
}
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
/* 是否有指定注解 */
boolean isAnnotationPresent = method.isAnnotationPresent(PojoPostProcessing.class);
if (!isAnnotationPresent) {
return;
}
/* 获取注解信息 */
PojoPostProcessing dpp = (PojoPostProcessing) method.getAnnotation(PojoPostProcessing.class);
this.logger.info("dpp : {}", dpp);
/* 只保留bean的指定属性值(其它属性值置空) */
logger.info("before bean : {}", returnObject);
BeanClearUtils.clearProperty(returnObject, dpp.whiteProperties());
logger.info("after bean : {}", returnObject);
}
}
使用注解:
@PojoPostProcessing(whiteProperties={"name", "createTime"})
【Java基础】Java注解简单入门的更多相关文章
- Java基础-Java中23种设计模式之常用的设计模式
Java基础-Java中23种设计模式之常用的设计模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.设计模式分类 设计模式是针对特定场景给出的专家级的解决方案.总的来说设 ...
- Java基础-Java数据类型
Java基础-Java数据类型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数据类型的作用 数据类型就是一组值,以及这一组值上的操作,数据类型可以决定数据的存储方式,取值范围 ...
- java基础---->java中正则表达式二
跟正则表达式相关的类有:Pattern.Matcher和String.今天我们就开始Java中正则表达式的学习. Pattern和Matcher的理解 一.正则表达式的使用方法 一般推荐使用的方式如下 ...
- Java基础-Java中的堆内存和离堆内存机制
Java基础-Java中的堆内存和离堆内存机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.
- Java基础-Java中的内存分配与回收机制
Java基础-Java中的内存分配与回收机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一. 二.
- Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock)
Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在学习Java的之前,你可能已经听说过读 ...
- Java基础-Java中的并法库之线程池技术
Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.
- Java基础-JAVA中常见的数据结构介绍
Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...
- 【转载】JAVA基础:注解
原文:https://www.cnblogs.com/xdp-gacl/p/3622275.html#undefined 一.认识注解 注解(Annotation)很重要,未来的开发模式都是基于注解的 ...
随机推荐
- 橡皮筋进度条ElasticProgressBar
橡皮筋进度条ElasticProgressBar 橡皮筋进度条是一个极具动画效果的进度条.该进度条不仅具有皮筋效果,还带有进度数据显示,让用户可以很清晰的看到当前的进度,可用于下载.加载进度等场景.E ...
- Java代码优化小结(三)
(35)对资源的close()建议分开操作虽然有些麻烦,却能避免资源泄露.我们想,如果没有修改过的代码,万一XXX.close()抛异常了,那么就进入了catch块中了,YYY.close()不会执行 ...
- URAL Palindromic Contest
A. Non-palidromic cutting 考虑无解的情形:只能是形如$aaaaa$.$aaabaaa$.$abababa$这三种情况. 有解时,对于最小划分,答案必定是$1$或者$2$,判断 ...
- Java 字符编码 ASCII、Unicode、UTF-8、代码点和代码单元
1 ASCII码 统一规定英语字符与二进制位之间的关系.ASCII码一共规定了128个字符的编码.例如,空格“SPACE”是32(二进制00100000),大写字母A是65(二进制01000001). ...
- 【组合数】[NOIP2011]选择客栈[c++]
题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均 ...
- JDBC(11)—数据库连接池
在实际开发过程中,特别是在web应用系统中,如果程序直接访问数据库中的数据,每一次数据访问请求丢必须经历建立数据库连接.打开数据库.存取数据和关闭数据库连接.而连接并打开数据库是一件既消费资源又费时的 ...
- poj1328 Radar Installation(贪心 策略要选好)
https://vjudge.net/problem/POJ-1328 贪心策略选错了恐怕就完了吧.. 一开始单纯地把island排序,然后想从左到右不断更新,其实这是错的...因为空中是个圆弧. 后 ...
- Codeforces909D Colorful Points(缩点)
http://codeforces.com/problemset/problem/909/D 直接模拟超时.要运用缩点的方法,把相同的一段缩成一点,记录有几个. 对于非首尾的缩点每次-2,首尾的-1. ...
- django之模型层(model)--建表、查询、删除基础
要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...
- .Net Core中的通用主机(二)——托管服务
前文介绍了.Net core的通用主机的配置,在基础配置完成后,下一步就是注册我们的后台任务了..net core提供了一个通用的后台服务接口IHostedService,称为托管服务.一个注册托管服 ...