Reflection框架可以:
获取某个类型的全部子类
只要类型、构造器、方法,字段上带有特定注解,便能获取带有这个注解的全部信息(类型、构造器、方法,字段)
获取所有能匹配某个正则表达式的资源
获取所有带有特定签名的方法,包括参数,参数注解,返回类型
获取所有方法的名字
获取代码里所有字段、方法名、构造器的使用
/* * 1.获取某个类型的全部子类
*2.只要类型、构造器、方法,字段上带有特定注解,便能获取带有这个注解的全部信息(类型、构造器、方法,字段)
* 3.获取所有能匹配某个正则表达式的资源
* 4.获取所有带有特定签名的方法,包括参数,参数注解,返回类型
* 5.获取所有方法的名字
* 6.获取代码里所有字段、方法名、构造器的使用
*/
public class Reflections {
//获取所有Inputstream的子类,限定只扫包前缀为“java”的,也就是jdk自带的
@Test
public void testPackage(){
org.reflections.Reflections reflections = new org.reflections.Reflections("java.");
Stopwatch stopwatch = Stopwatch.createStarted();
Set<Class<? extends InputStream>> allTypes = reflections.getSubTypesOf(InputStream.class);
System.out.println(stopwatch.toString());
for (Class type : allTypes) {
System.out.println("Found:"+type.getName());
}
}
// com.coding 包下的所有带有service注解的类
@Test
public void testAnnotationType(){
org.reflections.Reflections reflections = new org.reflections.Reflections("com.coding");
Stopwatch stopwatch = Stopwatch.createStarted();
Set<Class<?>> classes = reflections.getTypesAnnotatedWith(Service.class);
System.out.println(stopwatch.toString());
for (Class type : classes) {
System.out.println("Found:"+type.getName());
}
}
// 假如想扫描整个工程的类,直接new一个不带参数的Reflections就好。
// 值得一提的是,这东西在扫描的时候,连依赖的jar包都不放过。以Spring框架的BeanFactory为例:
@Test
public void testSubType2(){
org.reflections.Reflections reflections = new org.reflections.Reflections();
Set<Class<? extends BeanFactory>> classes = reflections.getSubTypesOf(BeanFactory.class);
for(Class clazz : classes) {
//logger.info(clazz.getName());
System.out.println("Found: " + clazz.getName());
}
}
// 所有带RequestMapping注解的方法
@Test
public void testAnnotationMethod(){
org.reflections.Reflections reflections = new org.reflections.Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage("com.coding"))
.addScanners(new MethodAnnotationsScanner()));
Set<Method> annotatedWith = reflections.getMethodsAnnotatedWith(RequestMapping.class);
for(Method p : annotatedWith) {
//logger.info(clazz.getName());
System.out.println("Found: " + p.getName());
}
}
// 所有properties文件
@Test
public void testResource(){
org.reflections.Reflections reflections = new org.reflections.Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage("com.coding"))
.addScanners(new ResourcesScanner()));
Set<String> properties =
reflections.getResources(Pattern.compile(".*\\.properties"));
for(String p : properties) {
//logger.info(clazz.getName());
System.out.println("Found: " + p);
}
}
// 所有带Deprecated注解的构造方法
@Test
public void testAnnotationConstractor(){
org.reflections.Reflections reflections = new org.reflections.Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage("com.coding"))
.addScanners(new MethodAnnotationsScanner()));
Set<Constructor> annotated = reflections.getConstructorsAnnotatedWith(Deprecated.class);
for(Constructor p : annotated) {
//logger.info(clazz.getName());
System.out.println("Found: " + p.getName());
}
}
// 所有带Id注解的构造方法
@Test
public void testAnnotationField(){
org.reflections.Reflections reflections = new org.reflections.Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage("com.coding"))
.addScanners(new FieldAnnotationsScanner()));
Set<Field> annotated = reflections.getFieldsAnnotatedWith(Id.class);
for(Field p : annotated) {
//logger.info(clazz.getName());
System.out.println("Found: " + p.getName());
}
}
// MethodParameterScanner 方法参数扫描器
@Test
public void testMethodParameter(){
org.reflections.Reflections reflections = new org.reflections.Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage("com.coding"))
.addScanners(new MethodParameterScanner()));
//MethodParameterScanner
Set<Method> someMethods =
reflections.getMethodsMatchParams(String[].class);
Set<Method> voidMethods =
reflections.getMethodsReturn(User.class);
Set<Method> pathParamMethods =
reflections.getMethodsWithAnyParamAnnotated(PathVariable.class);
for(Method p : someMethods) {
//logger.info(clazz.getName());
System.out.println("方法参数符合String[]的class:Found: " + p.getName());
}
for(Method p : voidMethods) {
//logger.info(clazz.getName());
System.out.println("返回值为User的方法:Found: " + p.getName());
}
for(Method p : pathParamMethods) {
//logger.info(clazz.getName());
System.out.println("参数带有PathVariable注解的方法:Found: " + p.getName());
}
}
// 测试框架自带的工具类
@Test
public void testReflectionUtils(){
// 所有get方法
Set<Method> getters = org.reflections.ReflectionUtils.getAllMethods(User.class,
org.reflections.ReflectionUtils.withModifier(Modifier.PUBLIC),
org.reflections.ReflectionUtils.withPrefix("get"),
org.reflections.ReflectionUtils.withParametersCount(0));
// 参数是Collection的子类,返回值是boolean
Set<Method> listMethodsFromCollectionToBoolean =
org.reflections.ReflectionUtils.getAllMethods(List.class,
org.reflections.ReflectionUtils.withParametersAssignableTo(Collection.class),
org.reflections.ReflectionUtils.withReturnType(boolean.class));
// field 带有Column注解,类型是String的子类
Set<Field> fields = org.reflections.ReflectionUtils.getAllFields(Docker.class,
org.reflections.ReflectionUtils.withAnnotation(Column.class),
org.reflections.ReflectionUtils.withTypeAssignableTo(String.class));
getters.forEach(get->System.out.println("getter:"+get));
listMethodsFromCollectionToBoolean.forEach(get->System.out.println("listMethodsFromCollectionToBoolean:"+get));
fields.forEach(get->System.out.println("fields:"+get));
}
}
最简单的配置,就是直接指定扫描包:
Reflections reflections = new Reflections("java.util");
@Test
public void config(){
ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
//扫描vip.mycollege.jdk.reflect包
Collection<URL> scannerPkg = ClasspathHelper.forPackage("vip.mycollege.jdk.reflect");
SubTypesScanner subTypesScanner = new SubTypesScanner();
//注解扫描
TypeAnnotationsScanner typeAnnotationsScanner = new TypeAnnotationsScanner();
FilterBuilder filter = new FilterBuilder()
.includePackage("vip.mycollege.jdk.reflect")//注解扫描包
.excludePackage("vip.mycollege.jdk.reflect.thirdpart");//注解扫描扫描排除包
typeAnnotationsScanner.filterResultsBy(filter);
ConfigurationBuilder configuration = configurationBuilder
.setUrls(scannerPkg)
.setScanners(subTypesScanner, typeAnnotationsScanner);
Reflections reflections = new Reflections(configuration);
}
- 通过类型扫描
@Test
public void newInstance(){
Reflections reflections = new Reflections("java.util");
//获取List及其子类
Set<Class<? extends List>> listImpls = reflections.getSubTypesOf(List.class);
listImpls.forEach(System.out::println);
}
- 通过注解扫描
@Test
public void methodAnnotationsScanner(){
Reflections reflections = new Reflections(SCAN_PKG);
//方法上有Deprecated注解
Set<Method> resources = reflections.getMethodsAnnotatedWith(Deprecated.class);
//有PostConstruct注解的构造方法
Set<Constructor> injectables = reflections.getConstructorsAnnotatedWith(PostConstruct.class);
}
@Test
public void FieldAnnotationsScanner(){
//指定包下有Nonnegative的字段
Reflections reflections = new Reflections(SCAN_PKG);
Set<Field> ids = reflections.getFieldsAnnotatedWith(Nonnegative.class);
}
- 方法相关
@Test
public void methodParameterScanner(){
Reflections reflections = new Reflections(SCAN_PKG);
//参数类型是long和int
Set<Method> someMethods = reflections.getMethodsMatchParams(long.class, int.class);
//参数返回值是void
Set<Method> voidMethods = reflections.getMethodsReturn(void.class);
//任何参数上有注解Nullable
Set<Method> pathParamMethods = reflections.getMethodsWithAnyParamAnnotated(Nullable.class);
for(Method method : someMethods) {
//获取方法参数的名称
List<String> parameterNames = reflections.getMethodParamNames(method);
parameterNames.forEach(System.out::println);
}
}
- 工具类
@Test
public void reflectionUtils(){
//必须是public方法
Predicate<Method> publicPredicate = ReflectionUtils.withModifier(Modifier.PUBLIC);
//有get前缀
Predicate<Method> getPredicate = ReflectionUtils.withPrefix("get");
//参数个数为0
Predicate<Member> paramPredicate = ReflectionUtils.withParametersCount(0);
Set<Method> methods = ReflectionUtils.getAllMethods(LinkedList.class, publicPredicate, getPredicate, paramPredicate);
methods.forEach(method -> System.out.println(method.getName()));
System.out.println("---------------");
//参数必须是Collection及其子类
Predicate<Member> paramsPredicate = ReflectionUtils.withParametersAssignableTo(Collection.class);
//返回类型是boolean
Predicate<Method> returnPredicate = ReflectionUtils.withReturnType(boolean.class);
methods = ReflectionUtils.getAllMethods(LinkedList.class, paramsPredicate, returnPredicate);
methods.forEach(method -> System.out.println(method.getName()));
System.out.println("---------------");
//字段有注解Native
Predicate<Field> annotationPredicate = ReflectionUtils.withAnnotation(Native.class);
//字段类型是int及其子类
Predicate<Field> typeAssignablePredicate = ReflectionUtils.withTypeAssignableTo(int.class);
Set<Field> fields = ReflectionUtils.getAllFields(Integer.class, annotationPredicate, typeAssignablePredicate);
// Set<Field> fields = ReflectionUtils.getAllFields(Integer.class, annotationPredicate);
// Set<Field> fields = ReflectionUtils.getAllFields(Integer.class, typeAssignablePredicate);
fields.forEach(field -> System.out.println(field.getName()));
基本上,要使用Reflections首先使用url和扫描程序实例化它
然后使用便捷的查询方法:(取决于配置的扫描仪)
//scan urls that contain 'my.package', include inputs starting with 'my.package', use the default scanners
Reflections reflections = new Reflections("my.package");
//or using ConfigurationBuilder
new Reflections(new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage("my.project.prefix"))
.setScanners(new SubTypesScanner(),
new TypeAnnotationsScanner().filterResultsBy(optionalFilter), ...),
.filterInputsBy(new FilterBuilder().includePackage("my.project.prefix"))
...);
//SubTypesScanner
Set<Class<? extends Module>> modules =
reflections.getSubTypesOf(com.google.inject.Module.class);
//TypeAnnotationsScanner
Set<Class<?>> singletons =
reflections.getTypesAnnotatedWith(javax.inject.Singleton.class);
//ResourcesScanner
Set<String> properties =
reflections.getResources(Pattern.compile(".*\\.properties"));
//MethodAnnotationsScanner
Set<Method> resources =
reflections.getMethodsAnnotatedWith(javax.ws.rs.Path.class);
Set<Constructor> injectables =
reflections.getConstructorsAnnotatedWith(javax.inject.Inject.class);
//FieldAnnotationsScanner
Set<Field> ids =
reflections.getFieldsAnnotatedWith(javax.persistence.Id.class);
//MethodParameterScanner
Set<Method> someMethods =
reflections.getMethodsMatchParams(long.class, int.class);
Set<Method> voidMethods =
reflections.getMethodsReturn(void.class);
Set<Method> pathParamMethods =
reflections.getMethodsWithAnyParamAnnotated(PathParam.class);
//MethodParameterNamesScanner
List<String> parameterNames =
reflections.getMethodParamNames(Method.class)
//MemberUsageScanner
Set<Member> usages =
reflections.getMethodUsages(Method.class)
如果未配置扫描仪,则将使用默认值-SubTypesScanner和TypeAnnotationsScanner。
还可以配置Classloader,该类加载器将用于从名称解析运行时类。
ReflectionUtils
ReflectionsUtils包含一些便捷的Java反射帮助器方法,用于获取与某些谓词匹配的类型/构造函数/方法/字段/注释,通常采用* getAllXXX(type,withYYY)的形式