如何改变类加载的双亲委派模式

package com.stand.job.common.classload;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

import com.stand.job.common.utils.ArrayUtils;

/**
 * 
 * @author chichaofan
 *
 *         如果delegateLoad 为false加载顺序如下
 * 
 *         bootstrapsclassload -> extclassload -> 自定义各种类加载器 -> systemclassload
 * 
 *         如果delegateLoad 为true为默认类加载器加载顺序如下
 * 
 *         bootstrapsclassload -> extclassload ->systemclassload -> 自定义各种类加载器
 */
public class StandJobClassLoader extends URLClassLoader {
	// 是否遵守双亲模式,默认双亲
	private boolean delegateLoad = true;

	private ClassLoader javaseClassLoader;

	StandJobClassLoader(boolean delegateLoad) {
		super(new URL[] {});
		this.delegateLoad = delegateLoad;
		setJavaseClassLoader();
	}

	StandJobClassLoader(ClassLoader parent, boolean delegateLoad) {
		super(new URL[] {}, parent);
		this.delegateLoad = delegateLoad;
		setJavaseClassLoader();
	}

	// 拷贝tomcat代码
	private void setJavaseClassLoader() {

		ClassLoader j = String.class.getClassLoader();
		if (j == null) {
			j = getSystemClassLoader();
			while (j.getParent() != null) {
				j = j.getParent();
			}
		}
		this.javaseClassLoader = j;
	}

	public void addJars(File[] files) {
		if (ArrayUtils.isEmpty(files)) {
			return;
		}

		for (File file : files) {

			addJar(file);

		}
	}

	public void addJar(File file) {

		if (file != null && file.isFile() && file.getName().toLowerCase().endsWith(".jar")) {

			try {
				addURL(file.toURI().toURL());
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}

		}
	}

	protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
		// 如果遵守双亲,调用原来
		if (delegateLoad) {

			return super.loadClass(name, resolve);

		}
		Class clazz = null;

		synchronized (getClassLoadingLock(name)) {
			/**
			 * 判断是否已经加载
			 */
			try {
				clazz = findLoadedClass(name);
				if (clazz != null) {
					if (resolve) {
						resolveClass(clazz);
					}
					return clazz;
				}
			} catch (Throwable e) {
			}
			/**
			 *  先有bootstrapsclassload和 extclassload加载
			 */
			try {
				clazz = javaseClassLoader.loadClass(name);
				if (clazz != null) {
					if (resolve) {
						resolveClass(clazz);
					}
					return clazz;
				}
			} catch (Throwable e) {
			}
			/**
			 * 再是最外层自定义classlaod加载
			 */
			try {
				clazz = super.findClass(name);

				if (clazz != null) {
					if (resolve) {
						resolveClass(clazz);
					}
					return clazz;
				}
			} catch (Throwable e) {
			}
			/**
			 * 最外层加载不了,调用默认后续的加载器继续加载
			 */
			try {
				clazz = super.loadClass(name, resolve);
				if (clazz != null) {
					if (resolve) {
						resolveClass(clazz);
					}
					return clazz;
				}
			} catch (Throwable e) {
			}
			/**
			 * 加载不了跑出异常
			 */
			throw new ClassNotFoundException();
		}
	}

}

测试例子:

测试类

package com.stand.job.example;

public class JobServiceTest {

	public void run() {
		System.out.println("hello world" + getClass().getClassLoader().getClass());
	}

}

测试main,在当前测试项目中加入以上jar包,运行以下代码

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException,
			IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		File file = new File("/Users/chichaofan/Documents/doc/workspace/example/target/");
		File[] files = file.listFiles(new FilenameFilter() {

			@Override
			public boolean accept(File dir, String name) {

				if (name.toLowerCase().endsWith(".jar")) {

					return true;
				}
				return false;

			}
		});
		for (File file2 : files) {
			StandJobClassLoader jobClassLoader = StandJobClassLoaderFactory.newInstance(false);

			jobClassLoader.addJar(file2);
			Object o = jobClassLoader.loadClass("com.stand.job.example.JobServiceTest").newInstance();
			ReflectUtils.findMethod(o.getClass(), "run").invoke(o);
		}

	}

当delegateLoad为false时输出

hello worldclass com.stand.job.common.classload.StandJobClassLoader

当delegateLoad为true时输出

hello worldclass sun.misc.Launcher$AppClassLoader

 

由此看出当delegateLoad为false时加载器的加载顺序被改变了

转载于:https://my.oschina.net/u/945573/blog/1572448

你可能感兴趣的:(如何改变类加载的双亲委派模式)