`
yanliebing
  • 浏览: 17284 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

自定义classLoader加载hibernate项目下的class文件并执行其中的代码

阅读更多
1 加载某一根目录下的class文件(此处代码转载)
public class TestClassLoader extends ClassLoader{
	
	private static final int CAPACITY = 1024;
	
	private String baseClassName;//根目录路径,例如某一个工程的classes目录
	
	public TestClassLoader(String baseClassName) {
		if (!baseClassName.endsWith(File.separator)) {
			this.baseClassName = baseClassName + File.separator;
		} else {
			this.baseClassName = baseClassName;
		}
	}

	protected Class<?> findClass(final String name) throws ClassNotFoundException {
		byte[] b = this.getByteFromClass(name);
		return this.defineClass(name, b, 0, b.length);
	}
	
	private byte[] getByteFromClass(final String name) {
		String path = StringUtils.replace(name, ".", File.separator) + ".class";
		File f = new File(baseClassName + path);
		if (!f.exists() || f.isDirectory()) {
			throw new RuntimeException(name + "is not exists!");
		}
		FileInputStream fileInput = null;
		
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		byte[] b = new byte[CAPACITY], classByte = null;
		try {
			int readLen;
			fileInput = new FileInputStream(f);
			
			while ((readLen = fileInput.read(b)) != -1) {
				byteArrayOutputStream.write(b, 0, readLen);
			}
			
			classByte = byteArrayOutputStream.toByteArray();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (fileInput != null) {
					fileInput.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				fileInput = null;
			}
			
			try {
				if (byteArrayOutputStream != null) {
					byteArrayOutputStream.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				byteArrayOutputStream = null;
			}
			
		}
		return classByte;
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		TestClassLoader loader = new TestClassLoader("H:/eclipse/workspace/hib/target/classes");
		Class employerManager = loader.loadClass("employ.Employer");
		System.out.println(employerManager.getName());
		Method[] methods = employerManager.getDeclaredMethods();
		for (Method method : methods) {
			System.out.println(method.getName());
		}
	}
}

2 利用URLClassLoader来加载jar包,主要代码如下:
 
URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
		   Method addURL = URLClassLoader.class.getDeclaredMethod("addURL",new Class[] { URL.class });
		   addURL.setAccessible(true);
		   
		   //add all the jar file path to classpath	   
		   for (File jarFile : jarFiles)
		   {
			   addURL.invoke(systemClassLoader, new Object[] { jarFile.toURL() });
		   } 
这部分代码主要用在服务器启动时加载一些jar包
3 自定义ClassLoader来加载jar包
  
public class MyClassLoader extends URLClassLoader {
	//加载类
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		return super.findClass(name);
	}


	public MyClassLoader(URL[] urls) {
		super(urls);
	}
	
	

	public MyClassLoader(URL[] urls, ClassLoader parent,
			URLStreamHandlerFactory factory) {
		super(urls, parent, factory);
		// TODO Auto-generated constructor stub
	}



	public MyClassLoader(URL[] urls, ClassLoader parent) {
		super(urls, parent);
		// TODO Auto-generated constructor stub
	}
	
	protected void addURL(URL url) {
		super.addURL(url);
	}
	
         //查找各种配置文件,例如hibernate.cfg.xml或者hibernate项目下各对象的.hbm.xml文件
	public URL findResource(final String name) {
		URL url = null;
		url = super.findResource(name);
		URL contextUrl = this.getResource(".");
                  //获取该类的classpath
		String contextPath = contextUrl.getPath();
		try {
			if (url == null) {
				if (name.startsWith(File.separator)) {
					String actualName = name.substring(1);
					url = new URL("file://" + contextPath + actualName);
				} else {
					url = new URL("file://" + contextPath + name);
				}
			}
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return url;
    }

}

  将该类可以放在在一java项目中。
   现在我们新建一hibernate项目,在该hibernate项目中,有一个EmployerManager类,该类功能实现是对员工进行管理,该类有一个getEmployer方法,其中类EmployerManager的getEmployer方法代码如下:
public List<Employer> getEmployer() {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		Criteria criteria = session.createCriteria(Employer.class);
		//criteria.add(Restrictions.le("id", 200L));
		criteria.setFirstResult(10);
		criteria.setMaxResults(50);
		List<Employer> employerList = (List<Employer>)criteria.list();
		for (Employer employer : employerList) {
			System.out.println(employer);
		}
		session.getTransaction().commit();
		return employerList;
	}


我们可以利用上述的MyClassLoader来加载hibernate工程下的classes目录下的jar包、classes文件以及xml配置文件
测试类如下(该测试类也在java项目中):
public class Test {
	
	public static void main(String[] args) throws ClassNotFoundException, IOException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, SecurityException, NoSuchMethodException {
		File f = new File("H:/eclipse/workspace/hib/target/classes/lib");
		String[] paths = f.list();
		//hib为hibernate工程名,该工程编译后的所有类文件都在H:/eclipse/workspace/hib/target/classes/目录下,同时将该项目用到的jar包放入H:/eclipse/workspace/hib/target/classes/lib目录下
		URL[] urls = {new URL("file:///H:/eclipse/workspace/hib/target/classes/")};
		MyClassLoader loader = new MyClassLoader(urls);
		for (String s : paths) {
			loader.addURL(new URL("file:///H:/eclipse/workspace/hib/target/classes/lib/" + s));
		}
				
		Class employerManager = loader.loadClass("employ.EmployerManager");
		
		Method[] methods = employerManager.getDeclaredMethods();
		for (Method method : methods) {
			if (method.getName().equals("getEmployer")) {
			
				method.invoke(employerManager.newInstance(), null);
			}
			
		}
		
	}
}


我们可以看到在Test类中执行该方法时会正确执行getEmployer的方法
4 总结:
  1  可以得到jar包的加载方法,这里对于采用获取jar包中每一个类文件的字节进行加载的方法不予介绍(javaeye上可以搜到)。
   2  对ClassLoader、URLClassLoader有了一定的了解。对如何加载类、加载jar包、加载资源文件有所了解。对于加载类,我们可以实现findClass方法,对于加载xml,我们可以实现findResource方法
   3  疑问:如果该java项目中的lib包中已经有另一hibernate中的某些包(例如hibernate-3.2.6.ga.jar),且这些包的版本相同或者不相同时结果会如何?冲突?
   4  对于类加载的安全性检查还没有实现。
分享到:
评论

相关推荐

    . .

    【描述】:在Java编程中,类加载是程序运行的基础,它负责将.class文件加载到JVM(Java虚拟机)中,以便程序可以使用其中的方法和数据。动态加载则是在运行时根据需要加载类,提高了程序的灵活性和扩展性。本文将...

    day17-类加载器和反射.zip

    在Java中,类加载器负责将类的字节码(.class文件)从磁盘加载到JVM(Java虚拟机)中,使程序能够执行这些类的方法和访问其属性。Java的类加载机制遵循“双亲委派模型”,这意味着当一个类加载器收到加载类的请求时...

    java注解_反射_字节码_类加载机制.zip

    类加载器(如Bootstrap ClassLoader、Extension ClassLoader、AppClassLoader)负责加载不同类型的类。双亲委派模型是类加载器之间的组织方式,确保类的唯一性。开发者可以通过自定义类加载器实现特定的加载逻辑,如...

    Java反射机制——类的加载方法,创建对象,获取方法以及结构

    - **加载**:类加载是将类的`.class`文件读入内存,并创建一个`java.lang.Class`对象。当使用类时,JVM会经历加载、连接和初始化三个步骤。 - **连接**:连接阶段包括验证、准备和解析。验证确保类的正确性;准备...

    Java类的反射与动态加载

    默认的ClassLoader会从classpath中查找.class文件,但我们可以自定义ClassLoader来从特定位置加载类。 6. 安全与性能: 反射操作比常规操作慢,因为它涉及了更多的运行时检查。同时,反射能够访问私有成员,可能会...

    Server Based Java Programming (Manning).pdf

    - **如何创建自定义类加载器**:通常通过继承`java.lang.ClassLoader`类并重写其方法来实现自定义类加载器。这涉及到如何读取类文件、验证类文件格式等技术细节。 ### 4. 扩展(Extensions) - **Java平台扩展机制**...

    实用工具类

    7. **获取项目文件路径**:在Java中,使用Class.getResource()或ClassLoader.getResource()可以获取到类路径下的文件路径,或者使用File类结合相对路径获取项目文件的实际路径。 8. **自动扫描FTP文件工具类**:FTP...

    出现几率最高和覆盖范围最广的一套经典Java面试题.docx

    - 自定义ClassLoader可以扩展加载自定义路径的类。 11. MVC架构 - Model:业务逻辑模型。 - View:用户界面。 - Controller:接收用户请求,处理后更新Model和View。 12. Struts工作流程 - 用户请求到达...

    springboot参考指南

    1. 介紹 2. I. Spring Boot文档 i. 1....ii. 2....iii....iv....v....vi....vii....3. II....i....ii....i....iii....i....i....ii....ii....i....ii....iii....iv....v....vi....iii....iv....v....vi....vii.... 编写代码 ... 自定义'白标'(whitelabel,可以了解下相关理念)错误页面 x. 71...

    大唐JAVA笔试题

    - 初始化:设置类变量的初始值并执行静态代码块。 - **层次结构**: - Bootstrap ClassLoader:最顶层,加载核心类库。 - Extension ClassLoader:加载扩展类库。 - Application ClassLoader:加载应用程序类。 #### ...

    JAVA基础综合资料

    它包括Bootstrap ClassLoader、Extension ClassLoader、System ClassLoader以及自定义的Web应用ClassLoaders。理解类加载器的层次结构和双亲委托模型,可以帮助优化应用性能和避免类冲突。 2. **各种排序算法的比较...

    java面试题集大全

    - 类加载器:Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader的职责。 - 堆内存和栈内存:对象的分配与回收,栈帧的理解。 - 类加载优化:双亲委派模型,类加载器的定制。 9. **Spring框架** - ...

    高薪面试题 java

    - **自定义Class**:理论上可以定义`java.lang.String`类,但实际开发中不允许这样做,因为JVM会直接加载该类,自定义版本无法被识别。 - **双亲代理机制**:子类加载器请求父类加载器完成类的加载工作,只有当父类...

    java面试八股文.pdf

    - 支持finally块确保某些代码无论是否发生异常都会被执行。 11. **静态绑定和动态绑定** - **静态绑定**:编译期确定调用哪个方法(如静态方法)。 - **动态绑定**:运行期确定调用哪个方法(如重写的方法)。 ...

    JDBC技术(二):数据库表的CRUD操作

    2. 加载驱动:使用`Class.forName()`方法加载数据库的JDBC驱动,使得Java虚拟机能够识别并处理特定数据库的SQL语法。 3. 获取连接:通过`DriverManager.getConnection()`方法,使用配置文件中的信息创建数据库连接。...

    Java面试题资料大全专对程序员刚毕业的提供帮助

    - 类加载机制:理解类加载过程,包括Bootstrap ClassLoader、Extension ClassLoader等。 - 反射API:Class类的使用,以及如何通过反射动态调用方法和访问属性。 8. **网络编程** - Socket编程:创建服务器端和...

    Java岗面试题库.7z

    - 类加载机制:Bootstrap ClassLoader、Extension ClassLoader、AppClassLoader。 - 获取类信息:Class类,Class.forName(),newInstance()。 - 动态调用方法和访问字段:Method、Constructor、Field。 8. **...

    百度2019年最新面试题库

    类加载器是Java虚拟机的一部分,负责将字节码加载到内存中,并转换为可执行的类。Java中有多种类加载器,包括Bootstrap ClassLoader、Extension ClassLoader和App ClassLoader。实现自定义类加载器可以帮助解决特定...

Global site tag (gtag.js) - Google Analytics