为什么说线程类加载器打破双亲委派,留了后门

 真正理解线程上下文类加载器

https://blog.csdn.net/yangcheng33/article/details/52631940

https://segmentfault.com/a/1190000017517197?utm_source=tag-newest

 

Java SPI的具体约定为:当服务的提供者提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。

public static <S> ServiceLoader<S> load(Class<S> service) {
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    return ServiceLoader.load(service, cl);
}

  

也就是说把自己加载不了的类加载到TCCL中(通过Thread.currentThread()获取,简直作弊啊!

ContextClassLoader默认存放了AppClassLoader的引用,由于它是在运行时被放在了线程中,所以不管当前程序处于何处(BootstrapClassLoader或是ExtClassLoader等),在任何需要的时候都可以用Thread.currentThread().getContextClassLoader()取出应用程序类加载器来完成需要的操作。

 

getConnection

由于TCCL本质就是当前应用类加载器,所以之前的初始化就是加载在当前的类加载器中,这一步就是校验存放的driver是否属于调用者的Classloader

 

tomcat与spring使用这种技术

 

归纳:

启动类加载器  interface A

系统类加载器   B implement A 

A a = (A)当前线程类加载器.loadclass(B).newInstance

List<A>.add(a);

List.get(x).run();

posted on 2020-01-08 13:25  silyvin  阅读(806)  评论(0编辑  收藏  举报