• 获取包名下的所有接口


    1 通过包名获取下面所有的类名集合

    2 通过类名集合反射获得类对象

    -->可以选择拿到标记自定义注解的接口 

    .filter(clazz -> clazz.getAnnotation(TrpcApi.class) != null)

    -->也可以不标记拿到全部接口

    3 通过类对象拿到所有的接口

    1. /**
    2. * 实现包扫描,通过包名拿到其下面所有的接口
    3. * @param packageName 包名
    4. */
    5. public RpcBootStart scan(String packageName) {
    6. //1根据包名拿到所有类名
    7. Listclassnames=getClassName(packageName);
    8. //2反射过滤后的接口集合
    9. //.filter(clazz -> clazz.getAnnotation(TrpcApi.class) != null)
    10. //用于只获取自己标记的接口,删除可变为标记全部
    11. List> classes = classnames.stream()
    12. .map(classname -> {
    13. try {
    14. //通过名字反射得到class对象
    15. return Class.forName(classname);
    16. } catch (ClassNotFoundException e) {
    17. throw new RuntimeException(e);
    18. }
    19. //过滤所有不含注解的类
    20. }).filter(clazz -> clazz.getAnnotation(TrpcApi.class) != null)
    21. .collect(Collectors.toList());
    22. for (Class clazz : classes) {
    23. //获取接口集合
    24. Class[] interfaces = clazz.getInterfaces();
    25. Object instance=null;
    26. try {
    27. instance= clazz.getConstructor().newInstance();
    28. } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
    29. e.printStackTrace();
    30. }
    31. }

    1 进行数据清洗,得到一个合适的路径,去除中文乱码,得到一个包的基本路径

    2 返回一个类名集合

    1. /**
    2. *
    3. * @param packageName 包名
    4. * @return 其下面---类名集合
    5. */
    6. private List getClassName(String packageName) {
    7. //1 获取绝对路径 转义拿到
    8. String basePath=packageName.replaceAll("\\.","/");
    9. URL url = ClassLoader.getSystemClassLoader().getResource(basePath);
    10. if (url == null){
    11. throw new RuntimeException("包扫描路径发生异常");
    12. }
    13. //转义包名
    14. String absolutePath = url.getPath();
    15. try {
    16. absolutePath = URLDecoder.decode(absolutePath, "utf-8");
    17. } catch (UnsupportedEncodingException e) {
    18. e.printStackTrace();
    19. }
    20. ArrayList classNames = new ArrayList<>();
    21. recursionFile(absolutePath,classNames,basePath);
    22. return classNames;
    23. }

     1 通过拿到基本路径去递归得到文件

    1. /**
    2. * 递归获取包名下所有类名
    3. * @param absolutePath 转义包名
    4. * @param classNames 所有类名
    5. */
    6. private ArrayList recursionFile( String absolutePath,ArrayList classNames,String basePath) {
    7. File file = new File(absolutePath);
    8. //判断是否是文件夹
    9. if (file.isDirectory()){
    10. File []childedFile=file.listFiles(new FileFilter() {
    11. @Override
    12. public boolean accept(File pathname) {
    13. return pathname.isDirectory() || pathname.getPath().contains(".class");
    14. }
    15. });
    16. if (childedFile.length==0 || childedFile==null) return classNames;
    17. for (File child : childedFile) {
    18. if (child.isDirectory()){
    19. //如果是文件价夹递归调用
    20. recursionFile(child.getAbsolutePath(),classNames,basePath);
    21. }else {
    22. //不是文件夹放在集合中
    23. String className= getClassNameByAbsolutePath(child.getAbsolutePath(), basePath);
    24. classNames.add(className);
    25. }
    26. }
    27. }else {
    28. //不是文件夹放在集合中
    29. String className= getClassNameByAbsolutePath(absolutePath, basePath);
    30. classNames.add(className);
    31. }
    32. return classNames;
    33. }

     再次进行数据清洗,得到所有.class开头的类的绝对路径加入集合返回

    1. /**
    2. *
    3. * @param absolutePath 当前包名
    4. * @param basePath 绝对包名路径
    5. * @return 类名的绝对路径
    6. */
    7. private String getClassNameByAbsolutePath(String absolutePath,String basePath) {
    8. //D:\0_项目管理\TRpc\TRpc_Framework\TRpc_Framework_Core\target\classes\com\trpc\channelHandler\ConsumerChannelInitializer.class
    9. //转成com\trpc\channelHandler
    10. String fileName = absolutePath.substring(
    11. absolutePath.indexOf(
    12. basePath.replaceAll("/","\\\\")
    13. )
    14. );
    15. //转成com.trpc.channelHandler
    16. fileName=fileName.replaceAll("\\\\", ".");
    17. fileName=fileName.substring(0,fileName.indexOf(".class"));
    18. return fileName;
    19. }

     

    标记注解:用于添加在接口上,添加是可以在包扫描是获取到该接口

    1. package com.trpc.annotation;
    2. import com.sun.istack.internal.Interned;
    3. import java.lang.annotation.ElementType;
    4. import java.lang.annotation.Retention;
    5. import java.lang.annotation.RetentionPolicy;
    6. import java.lang.annotation.Target;
    7. /**
    8. * 自定义注解
    9. */
    10. @Target(ElementType.TYPE) //在类上面使用
    11. @Retention(RetentionPolicy.RUNTIME) //允行时生效
    12. public @interface TrpcApi {
    13. }

     接口

    1. package com.trpc.api;
    2. import com.trpc.annotation.TryTimes;
    3. public interface HaloApi {
    4. String halo(String name);
    5. }

    需要添加在具体实现上 

    1. package com.trpc.service.Imp;
    2. import com.trpc.annotation.TrpcApi;
    3. import com.trpc.api.HaloApi;
    4. @TrpcApi
    5. public class HaloServiceImp implements HaloApi {
    6. @Override
    7. public String halo(String name) {
    8. return "halo"+name;
    9. }
    10. }

  • 相关阅读:
    猿创征文 | [云原生]为微服务保驾护航之链路跟踪skywalking保姆级搭建教程
    【服务发现--service】
    Bug排查思路
    HIVE操作自查手册(全)
    ActiViz中不规则网络数据体绘制技术介绍
    PCB设计笔记
    SQL批量处理+JDBC操作大数据及工具类的封装
    哈希表可以统计出现次数原理
    实现无公网IP环境下远程访问本地Jupyter Notebook服务的方法及端口映射
    【JavaScript进阶之旅 ES6篇 第九章】对象密封的四种方式、is()、assign()、取值函数的拷贝
  • 原文地址:https://blog.csdn.net/asmall_cat/article/details/132840034