• 获取包名下的所有接口


    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. }

  • 相关阅读:
    【css】H8_定位
    MySQL中的表与视图:解密数据库世界的基石
    分布式系统开发技术中的CAP定理原理
    Gradle多模块项目配置
    事件中的this指向、innerText的用法与考试题讲解
    Python基础篇(十三)-- 进程和线程
    Allegro Design Entry HDL(OrCAD Capture HDL)连线管理菜单详细介绍
    Ubuntu(Linux)的基本操作
    跨服务器迁移 Redis 数据
    Redis分布式缓存(一)| 单机安装、RDB和AOF持久化
  • 原文地址:https://blog.csdn.net/asmall_cat/article/details/132840034