前言
使用自定义注解,反射知识
一、了解一下基础
1、元注解(meta-annotation):
元注解可用于自定义注解。Java定义的元注解:
1).@Target //定义该注解可以使用在什么元素上,如类,接口等
2).@Retention //定义该注解的生命周期,
3).@Documented //是一个标记注解,如可标记在javadoc
4).@Inherited //是一个标记注解,阐述了某个被标注的类型是被继承的,如标记是否是class的子类
/** 元素类型 */
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration 声明为类、接口(包括注释类型)或枚举 */
TYPE,
/** Field declaration (includes enum constants)声明为字段(包括枚举常量) */
FIELD,
/** Method declaration 声明为方法 */
METHOD,
/** Formal parameter declaration 声明为正式的参数*/
PARAMETER,
/** Constructor declaration 声明为构造函数 */
CONSTRUCTOR,
/** Local variable declaration 声明为 */
LOCAL_VARIABLE,
/** Annotation type declaration 声明为注释类型 */
ANNOTATION_TYPE,
/** Package declaration 声明为包*/
PACKAGE,
/**
* Type parameter declaration 声明为类型参数
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type 类型的使用
* @since 1.8
*/
TYPE_USE
}
/** 生命周期的策略*/
public enum RetentionPolicy {
/** Annotations are to be discarded by the compiler.只在源文件保留,其它将被编译器丢弃 */
SOURCE,
/** Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.注释将被记录在编译器的类文件但不需要保留的虚拟机在运行时 */
CLASS,
/** 将由编译器记录在类文件中,并在运行时由VM保留,因此可以对它们进行反思读取
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
* @see java.lang.reflect.AnnotatedElement */
RUNTIME
}
2、自定义注解
1).定义注解格式:
public @interface 注解名 {定义体}
2).注解参数的可支持数据类型:
1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String类型
3.Class类型
4.enum类型
5.Annotation类型
6.以上所有类型的数组
3).Annotation类型里面的参数设定格式
类型 名称 [default 默认值]
二、自己动手_例子
1、自定义注解类
package com.myannotations;
import java.lang.annotation.*;
/**
* 自定义一个注解为PsAnnotation类
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD})
@Documented
//@Inherited
public @interface PsAnnotation {
String name() default "";
String attribute();
int num () default 0;
String[] pids();
}
2、使用注解的实体类
package com.myannotations;
/**
* 实体类
*/
@PsAnnotation(name = "psEntity", attribute ="pg" , pids ={"菜","刀"} )
public class PsEntity {
@PsAnnotation(name = "id",attribute = "1111", pids = {"sc"} )
public String id;
public String id2;
}
3、测试类
package com.myannotations;
import com.sun.deploy.util.StringUtils;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;
/**
* @PsAnnotation 自定义注解
* 测试类
*/
public class AnnotationText {
public static void main(String[] args) throws Exception {
new Thread(new Runnable() {
@Override
public void run() {
try {
//扫描某个包下的所有class 获取所有有注解的class ,属性
String packageName = "com.myannotations";
String packageDirName = packageName.replace('.', '/');
List<Class<?>> clazzs = new ArrayList<>();//所有的class
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while (urls != null && urls.hasMoreElements()) {
URL url = urls.nextElement();
//获取协议
String protocol = url.getProtocol();
if ("file".equals(protocol)) {
// 获取包的物理路径
String packagePath = URLDecoder.decode(url.getFile(), "UTF-8");
// 以文件的方式扫描整个包下的文件 并添加到集合中
findClassesInPackageByFile(packageName, packagePath, clazzs);
} else if ("jar".equals(protocol)) {
//todo
}
}
Map<String, Map<Method, Object>> methodInAnnotationMap = new HashMap<>();
Map<String, Class<?>> clazzInAnnotationMap = new HashMap<>();
Map<String, Map<Field, Object>> fieldInAnnotationMap = new HashMap<>();
for (Class<?> clazz : clazzs) {// 循环获取所有的类
if (clazz.getAnnotation(PsAnnotation.class) != null) {
clazzInAnnotationMap.put(clazz.getName(), clazz);
}
//获取所有属性
Field[] fields = clazz.getDeclaredFields();
Map<Field, Object> fieldObjectMap = new HashMap<>();
for (Field field : fields) {
field.setAccessible(true);
// 获取注解
Object annotation = field.getAnnotation(PsAnnotation.class);
if (annotation != null) {
fieldObjectMap.put(field, annotation);
}
if (fieldObjectMap.size() > 0)
fieldInAnnotationMap.put(clazz.getName(), fieldObjectMap);
}
// 获取类的所有方法
Method[] methods = clazz.getMethods();
Map<Method, Object> methodObjectMap = new HashMap<>();
for (Method method : methods) {
// 获取注解
Object annotation = method.getAnnotation(PsAnnotation.class);
if (annotation != null) {
methodObjectMap.put(method, annotation);
}
}
if (methodObjectMap.size() > 0)
methodInAnnotationMap.put(clazz.getName(), methodObjectMap);
}
for (Map.Entry<String, Class<?>> entry : clazzInAnnotationMap.entrySet()) {
PsAnnotation psAnnotation = entry.getValue().getAnnotation(PsAnnotation.class);
System.out.println("含有自定义注解的class :Key = " + entry.getKey() + ", psAnnotation = [" + psAnnotation.name().concat(",").concat(psAnnotation.attribute()));
}
System.out.println("===================================================================================================");
for (Map.Entry<String, Map<Field, Object>> entry : fieldInAnnotationMap.entrySet()) {
System.out.println("含有自定义注解的属性 :类 = " + entry.getKey());
for (Map.Entry<Field, Object> entry2 : entry.getValue().entrySet()) {
PsAnnotation psAnnotation = (PsAnnotation) entry2.getValue();
System.out.println("含有自定义注解的属性 : 属性 = " + entry2.getKey() + ", psAnnotation = [" + psAnnotation.name().concat(",").concat(psAnnotation.attribute()));
}
}
System.out.println("===================================================================================================");
for (Map.Entry<String, Map<Method, Object>> entry : methodInAnnotationMap.entrySet()) {
System.out.println("含有自定义注解的方法 :类 = " + entry.getKey());
for (Map.Entry<Method, Object> entry2 : entry.getValue().entrySet()) {
PsAnnotation psAnnotation = (PsAnnotation) entry2.getValue();
System.out.println("含有自定义注解的方法 : 方法 = " + entry2.getKey() + ", psAnnotation = [" + psAnnotation.name().concat(",").concat(psAnnotation.attribute()));
}
}
System.out.println("======================end===========================================================================");
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
public static void findClassesInPackageByFile(String packageName, String packagePath, List<Class<?>> clazzs) throws Exception {
// 获取此包的目录 建立一个File
File dir = new File(packagePath);
// 如果不存在或者 直接返回
if (!dir.exists()) {
return;
}
if (dir.isDirectory()) {
File[] files = dir.listFiles();
for (File file : files) {
// 如果是目录 则继续扫描
if (file.isDirectory())
findClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), clazzs);
else if (file.getName().endsWith(".class")) {
String className = file.getName().substring(0, file.getName().length() - 6);
clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
}
}
} else if (dir.getName().endsWith(".class")) {
// String name = dir.getPath();
String className = dir.getName().substring(0, dir.getName().length() - 6);
// 添加到集合中去
clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
}
}
}