获取包名下的所有接口

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

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

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

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

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

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

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

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

2 返回一个类名集合

 /**
     *
     * @param packageName 包名
     * @return 其下面---类名集合
     */
    private List getClassName(String packageName) {
        //1 获取绝对路径 转义拿到
        String basePath=packageName.replaceAll("\\.","/");
        URL url = ClassLoader.getSystemClassLoader().getResource(basePath);
        if (url == null){
            throw new RuntimeException("包扫描路径发生异常");
        }
        //转义包名
        String absolutePath = url.getPath();
        try {
            absolutePath = URLDecoder.decode(absolutePath, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        ArrayList classNames = new ArrayList<>();
        recursionFile(absolutePath,classNames,basePath);
        return classNames;
    }

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

/**
     * 递归获取包名下所有类名
     * @param absolutePath 转义包名
     * @param classNames 所有类名
     */
    private ArrayList recursionFile( String absolutePath,ArrayList classNames,String basePath) {
        File file = new File(absolutePath);
        //判断是否是文件夹
        if (file.isDirectory()){
            File []childedFile=file.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    return pathname.isDirectory() || pathname.getPath().contains(".class");
                }
            });
            if (childedFile.length==0 || childedFile==null) return classNames;

            for (File child : childedFile) {
                if (child.isDirectory()){
                    //如果是文件价夹递归调用
                    recursionFile(child.getAbsolutePath(),classNames,basePath);
                }else {
                    //不是文件夹放在集合中
                    String className= getClassNameByAbsolutePath(child.getAbsolutePath(), basePath);
                    classNames.add(className);
                }
            }
        }else {
            //不是文件夹放在集合中
            String className= getClassNameByAbsolutePath(absolutePath, basePath);
            classNames.add(className);
        }
        return classNames;
    }

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

/**
     *
     * @param absolutePath 当前包名
     * @param basePath 绝对包名路径
     * @return 类名的绝对路径
     */
    private String getClassNameByAbsolutePath(String absolutePath,String basePath) {
        //D:\0_项目管理\TRpc\TRpc_Framework\TRpc_Framework_Core\target\classes\com\trpc\channelHandler\ConsumerChannelInitializer.class
        //转成com\trpc\channelHandler
        String fileName = absolutePath.substring(
                absolutePath.indexOf(
                        basePath.replaceAll("/","\\\\")
                )
        );
        //转成com.trpc.channelHandler
        fileName=fileName.replaceAll("\\\\", ".");
        fileName=fileName.substring(0,fileName.indexOf(".class"));
        return fileName;
    }

 

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

package com.trpc.annotation;

import com.sun.istack.internal.Interned;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解
 */
@Target(ElementType.TYPE) //在类上面使用
@Retention(RetentionPolicy.RUNTIME) //允行时生效
public @interface TrpcApi {
}

 接口

package com.trpc.api;

import com.trpc.annotation.TryTimes;

public interface HaloApi {

    String halo(String name);
}

需要添加在具体实现上 

package com.trpc.service.Imp;

import com.trpc.annotation.TrpcApi;
import com.trpc.api.HaloApi;


@TrpcApi
public class HaloServiceImp implements HaloApi {
    @Override
    public String halo(String name) {
        return "halo"+name;
    }
}

你可能感兴趣的:(java,开发语言)