ServiceLoader类源码分析

本文详细探讨了Java中的ServiceLoader类,包括其使用方法和核心的forName方法,揭示了该类在加载服务实现时的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ServiceLoader类:

使用过程:

    public static void main(String[] args){
//       找到实现driver接口的数据库厂商的实现类
//       ServiceLoader:此方法先由系统类加载器来尝试加载,由双亲委托模型,此方法尝试使用boot
//        加载器来加载,根加载器可以成功加载。如果不使用ServiceLoader.load,则尝试使用boot来加载
//        Driver,而Driver在classpath路径下,不能由boot加载,加载失败    
        ServiceLoader<Driver>  loader = ServiceLoader.load(Driver.class);
        Iterator<Driver> iterator = loader.iterator();
//遵循SPI规范,去特定的目录寻找特定的文件然后解析出文件里的每一行,并且把每一行的信息读取出来,在
//需要的时候进行加载
        while (iterator.hasNext()){
            Driver driver = iterator.next();
            System.out.println("driver: " + driver.getClass()
                    + ", loader: " + driver.getClass().getClassLoader());
        }
        System.out.println("CurrentThreadClassLoader : " + Thread.currentThread().getContextClassLoader());
        System.out.println("ServiceLoader的类加载器 :"+  ServiceLoader.class.getClassLoader());
    }

方法解析:

 

    public static <S> ServiceLoader<S> load(Class<S> service) {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
//使用上下文类加载器,当前线程的上下文加载器(系统加载器)来加载
        return new ServiceLoader<>(Reflection.getCallerClass(), service, cl);
    }

ServiceLoader方法:

    private ServiceLoader(Class<?> caller, Class<S> svc, ClassLoader cl) {
        Objects.requireNonNull(svc);

        if (VM.isBooted()) {
            checkCaller(caller, svc);
            if (cl == null) {
                cl = ClassLoader.getSystemClassLoader();
            }
        } else {

            // if we get here then it means that ServiceLoader is being used
            // before the VM initialization has completed. At this point then
            // only code in the java.base should be executing.
            Module callerModule = caller.getModule();
            Module base = Object.class.getModule();
            Module svcModule = svc.getModule();
            if (callerModule != base || svcModule != base) {
                fail(svc, "not accessible to " + callerModule + " during VM init");
            }

            // restricted to boot loader during startup
            cl = null;
        }

        this.service = svc;
        this.serviceName = svc.getName();
        this.layer = null;
        this.loader = cl;                    //全局加载器设置为C1
        this.acc = (System.getSecurityManager() != null)
                ? AccessController.getContext()
                : null;
    }

下面方法中的forname方法特别关键:

        /**
         * Loads and returns the next provider class.
         */
        private Class<?> nextProviderClass() {
            if (configs == null) {
                try {
                    String fullName = PREFIX + service.getName();
                    if (loader == null) {
                        configs = ClassLoader.getSystemResources(fullName);
                    } else if (loader == ClassLoaders.platformClassLoader()) {
                        // The platform classloader doesn't have a class path,
                        // but the boot loader might.
                        if (BootLoader.hasClassPath()) {
                            configs = BootLoader.findResources(fullName);
                        } else {
                            configs = Collections.emptyEnumeration();
                        }
                    } else {
                        configs = loader.getResources(fullName);
                    }
                } catch (IOException x) {
                    fail(service, "Error locating configuration files", x);
                }
            }
            while ((pending == null) || !pending.hasNext()) {
                if (!configs.hasMoreElements()) {
                    return null;
                }
                pending = parse(configs.nextElement());
            }
            String cn = pending.next();
            try {
                return Class.forName(cn, false, loader);
//关键,loader为系统加载器(由上下文加载器设置出来的)
            } catch (ClassNotFoundException x) {
                fail(service, "Provider " + cn + " not found");
                return null;
            }
        }
   public static Class<?> forName(String name, boolean initialize,
                                   ClassLoader loader)
        throws ClassNotFoundException
    {
        Class<?> caller = null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            // Reflective call to get caller class is only needed if a security manager
            // is present.  Avoid the overhead of making this call otherwise.
            caller = Reflection.getCallerClass();
            if (loader == null) {
                ClassLoader ccl = ClassLoader.getClassLoader(caller);
                if (ccl != null) {
                    sm.checkPermission(
                        SecurityConstants.GET_CLASSLOADER_PERMISSION);
                }
            }
        }
        return forName0(name, initialize, loader, caller);
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值