Java中ServiceLoader实现方式

在java中根据一个子类获取其父类或接口信息非常方便,但是根据一个接口获取该接口的所有实现类却没那么容易。

有一种比较笨的办法就是扫描classpath所有的class与jar包中的class,然后用ClassLoader加载进来,然后再判断是否是给定接口的子类。但是很显然,不会使用这种方法,代价太大。

java本身也提供了一种方式来获取一个接口的子类,那就是使用java.util.ServiceLoader#load(java.lang.Class<S>) 方法,但是直接使用该方法也是不能获取到给定接口所有的子类的。

需要接口的子类以配置的方式主动注册到一个接口上,才能使用ServiceLoader进行加载到子类,并且子类需要有一个无参构造方法,用于被ServiceLoader进行实例化。

下面介绍ServiceLoader的实现步骤

1、编写Service

package com.linbe.ServiceLoader;

public interface Animal {
    void eat();
}

2、编写实现类(注意:实现类不一定要与接口在同一个工程中,可以存在于其他的jar包中)

package com.linbe.ServiceLoader;

public class Dog implements Animal {
    @Override
    public void eat() {
        System.out.println("Dog is eating...");
    }
}
package com.linbe.ServiceLoader;

public class Pig implements Animal {
    @Override
    public void eat() {
        System.out.println("Pig eating...");
    }
}

3、建立META-INF/services目录

在实现类所在的工程的classpath下面的建立META-INF/services目录,该目录是固定的,一定要按照规定的名称去创建,该目录用于配置接口与实现类的映射关系;然后根据接口全名 在该目录创建一个文件,例如上面例子中接口全名是com.linbe.ServiceLoader.Animal,那么就需要在实现类的工程中建立META-INF/services/com.linbe.ServiceLoader.Animal这样一个文件,然后在该文件中配置该接口的实现类,如果该接口有多个实现类,一行写一个(以换行符分割),例如:

com.linbe.ServiceLoader.Dog
com.linbe.ServiceLoader.Pig

4、使用ServiceLoader的方法获取子类

package com.linbe.ServiceLoader;

import java.util.Iterator;
import java.util.ServiceLoader;

public class TestServiceLoader {
    public static void main(String[] args) {
        ServiceLoader<Animal> serviceLoader = ServiceLoader.load(Animal.class);
        Iterator<Animal> iter = serviceLoader.iterator();
        while (iter.hasNext()) {
            Animal animal = iter.next();
            animal.eat();
        }
    }
}

输出:

Dog is eating...
Pig eating...

JDK的ServiceLoader通过返回一个Iterator对象能够做到对服务实例的懒加载 只有当调用iterator.next()方法时才会实例化下一个服务实例,只有需要使用的时候才进行实例化,具体实现读者可以去阅读源码进行研究,这也是其设计的亮点之一。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值