参考待整理:https://www.cnblogs.com/yzykkpl/p/10356258.html
获取注解
你需要通过反射来获取运行时注解,可以从 Package、Class、Field、Method...上面获取,基本方法都一样,几个常见的方法如下:
/** * 获取指定类型的注解 */ public <A extends Annotation> A getAnnotation(Class<A> annotationType); /** * 获取所有注解,如果有的话 */ public Annotation[] getAnnotations(); /** * 获取所有注解,忽略继承的注解 */ public Annotation[] getDeclaredAnnotations(); /** * 指定注解是否存在该元素上,如果有则返回true,否则false */ public boolean isAnnotationPresent(Class<? extends Annotation> annotationType); /** * 获取Method中参数的所有注解 */ public Annotation[][] getParameterAnnotations();
1.java 自定义注解 (原文:https://blog.csdn.net/github_35180164/article/details/52118286)
注解:
// 适用类、接口(包括注解类型)或枚举 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ClassInfo { String value(); } // 适用field属性,也包括enum常量 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface FieldInfo { int[] value(); } // 适用方法 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MethodInfo { String name() default "long"; String data(); int age() default 27; }
定义一个测试类来使用这些注解:
/** * 测试运行时注解 */ @ClassInfo("Test Class") public class TestRuntimeAnnotation { @FieldInfo(value = {1, 2}) public String fieldInfo = "FiledInfo"; @FieldInfo(value = {10086}) public int i = 100; @MethodInfo(name = "BlueBird", data = "Big") public static String getMethodInfo() { return TestRuntimeAnnotation.class.getSimpleName(); } }
获取注解信息:
/** * 测试运行时注解 */ private void _testRuntimeAnnotation() { StringBuffer sb = new StringBuffer(); Class<?> cls = TestRuntimeAnnotation.class; Constructor<?>[] constructors = cls.getConstructors(); // 获取指定类型的注解 sb.append("Class注解:").append("\n"); ClassInfo classInfo = cls.getAnnotation(ClassInfo.class); if (classInfo != null) { sb.append(Modifier.toString(cls.getModifiers())).append(" ") .append(cls.getSimpleName()).append("\n"); sb.append("注解值: ").append(classInfo.value()).append("\n\n"); } sb.append("Field注解:").append("\n"); Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { FieldInfo fieldInfo = field.getAnnotation(FieldInfo.class); if (fieldInfo != null) { sb.append(Modifier.toString(field.getModifiers())).append(" ") .append(field.getType().getSimpleName()).append(" ") .append(field.getName()).append("\n"); sb.append("注解值: ").append(Arrays.toString(fieldInfo.value())).append("\n\n"); } } sb.append("Method注解:").append("\n"); Method[] methods = cls.getDeclaredMethods(); for (Method method : methods) { MethodInfo methodInfo = method.getAnnotation(MethodInfo.class); if (methodInfo != null) { sb.append(Modifier.toString(method.getModifiers())).append(" ") .append(method.getReturnType().getSimpleName()).append(" ") .append(method.getName()).append("\n"); sb.append("注解值: ").append("\n"); sb.append("name: ").append(methodInfo.name()).append("\n"); sb.append("data: ").append(methodInfo.data()).append("\n"); sb.append("age: ").append(methodInfo.age()).append("\n"); } } System.out.print(sb.toString()); }
测试结果:
2.SpringBoot 自定义注解
annotation注解:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 自定义注解,实现主键自增 * @author sea * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface AutoIncKey {}
AutoIncKeyEventListener 注解监听器:
package com.sea.test.annotation; import java.lang.reflect.Field; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.FindAndModifyOptions; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Component; import org.springframework.util.ReflectionUtils; /** * 监听器用于监听MongoEvent * ,该类继承AbstractMongoEventListener类,因为我们需要在JAVA对象转换成数据库对象的时候操作id字段实现id自增, * 所以覆盖onBeforeConvert方法(详见spring-data文档,https://docs.spring.io/spring-data/data-document/docs/current/reference/html/,5.11节) * @author sea * */ @Component public class AutoIncKeyEventListener extends AbstractMongoEventListener<Object>{ private static final Logger logger= LoggerFactory.getLogger(AutoIncKeyEventListener.class); @Autowired private MongoTemplate mongoTemplate; @Override public void onBeforeConvert(BeforeConvertEvent<Object> event) { logger.info(event.getSource().toString()); Object source = event.getSource(); if (source != null) { ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() { public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { ReflectionUtils.makeAccessible(field); // 如果字段添加了我们自定义的AutoIncKey注解 if (field.isAnnotationPresent(AutoIncKey.class)) { // 设置自增ID Object value = field.get(source); //获取之前id的值,如果主键不为空,主键加1 if(value==null) { field.set(source, getNextId(source.getClass().getSimpleName())); } } } }); } } private Long getNextId(String collName) { Query query = new Query(Criteria.where("collName").is(collName)); Update update = new Update(); update.inc("seqId", 1); FindAndModifyOptions options = new FindAndModifyOptions(); options.upsert(true); options.returnNew(true); SeqInfo seq = mongoTemplate.findAndModify(query, update, options, SeqInfo.class); return seq.getSeqId(); } }
序列id
SeqInfo
import java.io.Serializable; public class SeqInfo implements Serializable { private static final long serialVersionUID = 1L; private Long seqId; public Long getSeqId() { return seqId; } public void setSeqId(Long seqId) { this.seqId = seqId; } }