如何裸写或利用Spring扫描出指定包下的所有类名

22 篇文章 1 订阅

在很多Java框架中都有组件扫描功能,即给出一个注解,框架能够把所有标注了此注解的类找出来。这种操作的本质是给出一个名包,能获取到此包下的所有类名,然后再通过反射判断是否加了指定的注解。无论是什么框架,包括Spring, 完成这个功能底层都是用的ClassLoader.getResources()ClassLoader.getSystemResources()方法实现的,即先找出指定classpath下的"资源",可能是文件也可能是jar包,然后通过文件I/O读取jar, 把每一个.class文件名全部列出即可。如果我们要自己手写这样的功能的话就必须参照这个思路去实现,但是逻辑比较复杂,主要是很多细节问题需要注意。这里有一个我自己实现的PkgScanner可供参考,github: https://github.com/wanghongfei/pkg-scanner

当然,多数时候我们并不想自己重复造轮子。Spring就有现成的类可以让我们直接使用, 它们分别是ResourcePatternResolverCachingMetadataReaderFactory,使用方法如下:

public class ScanTest extends BaseTestClass implements ResourceLoaderAware {
    /**
     * Spring容器注入
     */
    private ResourceLoader resourceLoader;

    @Test
    public void test() throws IOException {

        ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
        MetadataReaderFactory metaReader = new CachingMetadataReaderFactory(resourceLoader);
        Resource[] resources = resolver.getResources("classpath*:your/package/name/**/*.class");

        for (Resource r : resources) {
            MetadataReader reader = metaReader.getMetadataReader(r);
            System.out.println(reader.getClassMetadata().getClassName());
        }

    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}

在我的项目里,这个单测的输出是:
output
可见已经完全满足了要求。

如果去深究源码实现,最终你会在PathMatchingResourcePatternResolver类的doFindAllClassPathResources()方法中找到答案:
code
即,本质还是扫描jar包,读取jar包。

其实这个功能最好直接集成到JDK的类库中,这样大家就不必绕这么大圈子来实现这个看似简单但逻辑又非常复杂的功能了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值