spring忽略类加载器

mpbci0fu  于 2021-07-12  发布在  Java
关注(0)|答案(0)|浏览(176)

Java9和Java11经常需要使用定制的类加载器。所以我创造了一个 BootstrapClassloader 它预装了我的类路径,我使用 Thread.currentThread().setContextClassLoader(classloader) 使其成为默认值。
我很快发现spring在加载上下文时恢复到原来的应用程序类加载器 new ClassPathXmlApplicationContext() .
没问题,我想,并写了一个变种我呼吁 BootstrapClassLoader 试图强迫spring使用我的类加载器。但是spring仍然忽略了我的类加载器。
例如,我验证了aopalliance-1.0.jar在类加载器的类路径中,可以手动加载 MethodInterceptor . 但是如果我有一个带有标准dbcp2数据源bean的上下文(取决于aopalliance),它会抛出一个 ClassNotFoundException 为了 org.aopalliance.intercept.MethodInterceptor .
有人能看到下面代码中的一个缺陷吗,或者是否有某种特殊的方法来注册类加载器,以便spring在应用程序中始终使用它?
数据源代码段:

<bean id="msSqlDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName"            value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
    <property name="validationQuery"            value="select 1" />
  </bean>
  <bean id="dbEmailDataSource" parent="msSqlDataSource"  class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" lazy-init="true">
    <property name="url"                        value="" />
    <property name="username"                   value="" />
    <property name="password"                   value="" />
  </bean>

测试应用代码:

public static void main(String[] args) {
    try {
      Bootstrap.init();
      for(String urlName : Bootstrap.getClasspathUrlNames()) {
        if(StringUtils.containsIgnoreCase(urlName, "aopalliance")) {
          System.out.println(urlName);
        }
      }
      ConfigurableApplicationContext ctx = new BootstrappedApplicationContext("DbEmailContext.xml");

      ctx.close();
    }catch(Throwable t) {
      t.printStackTrace();
    }
    try {
      Class clazz = Bootstrap.getClassLoader().loadClass("org.aopalliance.intercept.MethodInterceptor");
      System.out.println("manually loaded:  "+clazz.getName());
    }catch(Throwable t) {
      t.printStackTrace();
    }
  }

bootstrappedapplicationcontext(类似于classpathxmlapplicationcontext):

public class BootstrappedApplicationContext extends AbstractXmlApplicationContext {

  private URLClassLoader classloader;
  private Resource[] configResources;

  public BootstrappedApplicationContext() {
    super();
    this.classloader = Bootstrap.getClassLoader();
    super.setClassLoader(this.classloader);
  }

  public BootstrappedApplicationContext(ApplicationContext parent) {
    this();
    setParent(parent);
  }

  public BootstrappedApplicationContext(String configLocation) 
  throws BeansException {
    this(new String[] {configLocation}, true, null);
  }

  public BootstrappedApplicationContext(String... configLocations) 
  throws BeansException {
    this(configLocations, true, null);
  }

  public BootstrappedApplicationContext(String[] configLocations, ApplicationContext parent) 
  throws BeansException {
    this(configLocations, true, parent);
  }

  public BootstrappedApplicationContext(String[] configLocations, boolean refresh) 
  throws BeansException {
    this(configLocations, refresh, null);
  }

  public BootstrappedApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
  throws BeansException {
    this(parent);
    setConfigLocations(configLocations);
    if(refresh) {
      refresh();
    }
  }

  public BootstrappedApplicationContext(String path, Class<?>clazz)
  throws BeansException {
    this(new String[] {path}, clazz);
  }

  public BootstrappedApplicationContext(String[] paths, Class<?> clazz) throws BeansException {
    this(paths, clazz, null);
  }

  public BootstrappedApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent)
      throws BeansException {
    this(parent);
    Assert.notNull(paths, "Path array must not be null");
    Assert.notNull(clazz, "Class argument must not be null");
    this.configResources = new Resource[paths.length];
    for (int i = 0; i < paths.length; i++) {
      this.configResources[i] = new ClassPathResource(paths[i], clazz);
    }
    refresh();
  }

  @Override
  public ClassLoader getClassLoader() {
    if(classloader == null) {
      classloader = Bootstrap.getClassLoader();
    }
    super.setClassLoader(classloader);
    return classloader;
  }

  public void setClassLoader(URLClassLoader classloader) {
    this.classloader = classloader;
    super.setClassLoader(classloader);
  }

  @Override
  protected Resource[] getConfigResources() {
    return this.configResources;
  }
}

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题