Skip to main content Link Menu Expand (external link) Document Search Copy Copied

1. maven库

使用这个库,加上注解的类,编译后,在META-INFO目录下,生成配置文件


<dependency>
    <groupId>org.kohsuke.metainf-services</groupId>
    <artifactId>metainf-services</artifactId>
    <version>${metainf-services.version}</version>
    <scope>compile</scope>
</dependency>

@MetaInfServices(InspectorPlugin.class)

2. java加载SPI

Java的SPI机制就是指:针对一个接口,我们需要加载外部对该接口的实现, 只要约定好将该实现配置在classPath路径下的META-INF/services文件夹的文件,使用方就可以自动加载文件里所定义的类。

SPI中三个重要的角色:

  • 接口
public interface InspectorPlugin {

    String identify();

    boolean enable(List<String> plugins);

    boolean entrance();

    int watch(ModuleEventWatcher watcher, InvocationSendService service);

}
  • 配置文件

@MetaInfServices(InspectorPlugin.class)
public class DubboProviderPlugin extends BasePlugin {
    public DubboProviderPlugin(InvocationSendService invocationSendService) {
        super(Constant.DUBBO_PROVIDER, true, invocationSendService);
    }


    @Override
    public void watch(ModuleEventWatcher watcher) {
        new EventWatchBuilder(watcher)
                .onClass("org.apache.dubbo.rpc.filter.ContextFilter").includeBootstrap()
                .onBehavior("invoke")
                .onWatch(new DubboProviderEventListener(entrance, protocol, invocationSendService), Event.Type.BEFORE, Event.Type.RETURN, Event.Type.THROWS);
    }
}
  • ServiceLoader反射获取
private List<InspectorPlugin> loadInspectorPluginBySPI( ClassLoader classLoader) {
        ServiceLoader<InspectorPlugin> loaded = ServiceLoader.load(InspectorPlugin.class, classLoader);
        Iterator<InspectorPlugin> spiIterator = loaded.iterator();
        List<InspectorPlugin> target = Lists.newArrayList();
        while (spiIterator.hasNext()) {
            try {
                target.add(spiIterator.next());
            } catch (Throwable e) {
                log.error("Error load spi InspectorPlugin >>> ", e);
            }
        }
        return target;
    }