java 接口 实现类_获取Java接口的所有实现类

获取Java接口的所有实现类

前言:想看基于spring 的最简单实现方法,请直接看 第七步。

本文价值在于包扫描的原理探究和实现

一、背景

项目开发中,使用Netty做服务端,保持长连接与客户端(agent)通讯。Netty服务端需要根据不同消息类型,加载对应的Processer(消息处理器)对消息进行处理。问题就出现了,Processer会随着消息业务类型增多进行扩展,每一次增加Processer都需要手动new出来一个实例,放到Map里(key为消息类型码,value为Processer实例),供调度程序(ProcesserManager)根据端消息类型调度,显然这是件很麻烦的一件事,不仅操作琐碎,也不符合低耦合、模块化的设计思想。

二、解决思路

我们所写的每一个Processer都是IProcessor这个接口的实现:

public interface IProcessor {

void process(BaseMsgWrapper msg) throws Exception;

EventEnum getType();

default String getIpFromChannelContext(ChannelHandlerContext ctx){

String[] ipPort = ctx.channel().remoteAddress().toString().split(":");

return ipPort[0].substring(1);

}

}

其中:

void process(BaseMsgWrapper msg)  为消息处理方法

void getIpFromChannelContext (BaseMsgWrapper msg)  为获取客户端ip的默认方法

假如我们在Netty服务端启动时,能获取该接口的所有实现类,然后把这些实现类分别new出来,放到Map中,那么这个工作就可以自动化掉了。

最终实现的效果就是 消息处理器只要 implements IProcessor接口,就会被自动加载调用,而不再需要手动写到Map中。这样就将ProcesserManager 与 Processer解耦开了。

为此,IProcessor接口需要增加一个方法

EventEnum getType();

即需要Processer表明自己对应的消息类型,没这个方法之前,我们都是在put进Map的时候,手动把消息类型写进去的(可以想象之前的做法多么的low)

三、实现过程

想法是很好,但实现不是那么容易,踩了很多坑。

首先是网上查资料,看看其他人都怎么做的,有没有做好的轮子。

这篇博客提供的大致思路:

1) 获取当前线程的ClassLoader

2) 通过ClassLoader获取当前工作目录,对目录下的文件进行遍历扫描。

3) 过滤出以.class为后缀的类文件,并加载类到list中

4) 对list中所有类进行校验,判断是否为指定接口的实现类,并排除自身。

5) 返回所有符合条件的类。

这个思路是对的,但是考虑不全,不能拿来工程应用,另外博文中提供的源码应该只是一个实验代码,有不少缺陷。

1)这个方没有考虑不同的文件格式。当程序打成jar包,发布运行时,上述的这种遍历file的操作 就失效了。

2)局限性。只能扫描到当前方法的同级目录及其子目录。无法覆盖整个模块。

3)遍历文件的逻辑太啰嗦,可以简化。

4)通过ClassLoader获取当前工作目录时,使用了“../bin/”这么一个固定的目录名。

Enumeration enumeration = classLoader.getResources("../bin/" + path)

事实上,不同的IDE(主要是eclipse 和 idea)项目的资源目录,在这一点上是不同的。

第二篇博客参考:

(获取全部子类或接口的全部实现)

这篇博客考虑到了在运行环境中,需要通过JarFile工具类进行单独处理。

局限性:

需要手动指定要扫描的Jar文件或目录,没有通过ClassLoader 自动获取当前运行的上下文。

此外classLoader.getResource 获得的 资源目录 是个URL对象,如何转换成JarFile对象 花费了我不少时间求索:

JarURLConnection jarURLConnection = (JarURLConnection)url.openConnection();

JarFile

jarFile = jarURLConnection.getJarFile();

综合上述思路和自己的试验研究,得出获取接口所有实现类的算法流程如下:

97d34c4727ac571be648e6446bc320ea.png

四、代码实现

package com.hikvisio

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值