前言
今天复习了一下注解知识,想到类似与一些 反射包 可以直接扫描包的这个功能,于是乎我花了一点点时间,也做了一个类似功能,有需要的可以了解一下思路
定义注解
annation包
/**
* 角色
*
* @author Marinda
* @date 2022/10/22
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Role {
String name();
String role() default "成员";
}
定义实现类
handle包
User.java
package cn.marinda.handle;
import cn.marinda.annotaion.Role;
public class User {
@Role(name = "小红",role = "管理员")
public void xiaoHong(){}
@Role(name = "小明")
public void xiaoMing(){}
}
package cn.marinda.handle;
import cn.marinda.annotaion.Role;
import cn.marinda.annotaion.UserAnnotaion;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
public class UserHandle {
public List<Class> getClassListByPackage(String packageName){
// 定义List
List<Class> classList = new ArrayList<>();
// 获取根目录
String userDir = System.getProperty("user.dir");
// 获取Src地址
String srcPath = userDir.concat("/src");
// File遍历
File srcFile = new File(srcPath);
// 定义List列表储存包名
List<File> packageFileList = new ArrayList<>();
// 如果是目录
getPackageFileList(srcFile,packageFileList);
// 验证是否存在这个包名
if(!validPackageExists(packageName,packageFileList)){
// 不存在包名
return null;
}
// 储存
Map<String,List<String>> packageMap = new HashMap<>();
// 遍历包文件
packageFileList.forEach((ele)->{
// 获取包下的class信息
packageMap.putAll(getPackageClassInfo(ele));
});
// 开始获取包注解信息
List<String> classInfo = packageMap.get(packageName);
queryAnnotaion(classInfo,packageName);
return null;
}
/**
* 执行
*
* @param classInfo 类信息
* @param packageName 包名
*/
void queryAnnotaion(List<String> classInfo,String packageName){
//
String parentPath = "cn.marinda".concat(".".concat(packageName));
System.out.println("ParentPath: " + parentPath);
try {
for (String className : classInfo) {
String path = parentPath.concat(".".concat(className));
System.out.println("Path: "+ path);
Class cl = Class.forName(path);
// 获取方法
Method[] methods = cl.getDeclaredMethods();
for (Method method : methods) {
Annotation[] annotations = method.getAnnotations();
// System.out.println("注解数量:" + annotations.length);
// 有效注解
if(annotations.length > 0){
for(Annotation annotation : annotations){
if(annotation instanceof Role){
Role role = (Role) annotation;
System.out.println(String.format("名称:%s, 身份: %s",role.name(),role.role()));
}
}
}
}
continue;
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 验证包名是否存在
*
* @return boolean
*/
boolean validPackageExists(String packageName,List<File> packageFileList){
boolean flag = false;
for (File file : packageFileList) {
if(file.getName().equalsIgnoreCase(packageName)){
flag = true;
}
}
return flag;
}
/**
* 递归获取包名列表
*
* @param dirFile dir文件
*/
void getPackageFileList(File dirFile,List<File> packageList){
for(File listFile : dirFile.listFiles()){
if(listFile.isDirectory()){
for (File file : listFile.listFiles()) {
// 目录下有文件的包名
if(file.isFile()){
// 不添加带有启动类的包
if(!file.getName().equalsIgnoreCase("Main.java")){
if(!packageList.contains(listFile)){
System.out.println("file: " + listFile.getPath());
packageList.add(listFile);
}
}
continue;
}
}
}
// 如果是文件则停止
if(listFile.isFile()){
break;
}
// 递归
getPackageFileList(listFile,packageList);
}
}
/**
* 通过包获取类文件名称
*
* @param packageFile 包文件
* @return {@link Map}<{@link String}, {@link String}>
*/
Map<String,List<String>> getPackageClassInfo(File packageFile){
Map<String,List<String>> classNameMap = new HashMap<>();
File file = new File(packageFile.getPath());
ArrayList list = new ArrayList();
Arrays.stream(file.listFiles()).forEach((ele)->{
String className = ele.getName().replace(".java","");
list.add(className);
classNameMap.put(packageFile.getName(),list);
});
return classNameMap;
}
@UserAnnotaion({"你好","我是小明"})
public void test(){
try {
Class<UserHandle> userHandleClass = UserHandle.class;
Annotation[] annotations = userHandleClass.getAnnotations();
System.out.println("获取方法的注解数据");
Method method = userHandleClass.getMethod("test");
UserAnnotaion annotation = method.getAnnotation(UserAnnotaion.class);
for(String str : annotation.value()){
System.out.println("方法注解数据:"+ str);
}
}catch (Exception e){
e.printStackTrace();
}
}
@UserAnnotaion({"小明"})
public void xiaoMing(){
}
@UserAnnotaion("小红")
public void xiaoHong(){
}
}
运行结果
温馨提示
该扫描功能实现是来自于File进行监测
结束语
Java学习笔记 —— 指定包名扫描包下所有类并获取相关注解信息
- 如果对你有帮助的话可以给我点赞收藏,十分感谢
- 致力做优、好、细、精学习笔记分享给大家
- 可以转载 需标明 出处 本文链接。
- 笔者一个开源项目:我的世界开服助手 希望大家可以点一下star哦
感谢你的观看。