Java运行时动态加载类之ClassLoader

https://blog.csdn.net/fjssharpsword/article/details/64922083

***************************************************************************

需求场景:动态加载类ClassLoaderd,在xml文件中配置加载类名称和方法,:

一、准备

1)在D:\\tmp\\目录下配置a.xml文件:

<?xml version="1.0" encoding="ISO-8859-1"?>
<classes>

 <class name="User">
 <method>say</method>
 </class> 

 <class name="map">
 <method>add</method>
 </class> 

</classes>

2)要动态加载的类:

package dx;

public class map {
    public void add(){
        System.out.println("1+1=2");
    }
}
package cn.fjs;

public class User {

    public void say(){
        System.out.println(" hello ...");
    }

}

对这两个类进行编译后,将class文件复制到D:\\tmp\\路径下。

二、参考代码如下

1、重载ClassLoader类:

package cn.fjs;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;

public class DynamicClassLoader extends ClassLoader{

    private static final String SUFFIX = ".class";
    public String[] paths;

    public DynamicClassLoader(String[] paths) {
        this.paths = paths;
    }

    public DynamicClassLoader(ClassLoader parent,String[] paths){
        super(parent);
        this.paths = paths;
    }

    @SuppressWarnings("deprecation")
    @Override
    protected Class<?> findClass(String className) throws ClassNotFoundException {
        String classPath = getClassPath(className);
        if(classPath != null){
            byte[] clazz = loadClazz(classPath);
            return defineClass(clazz, 0, clazz.length);
        }else{
            System.out.println("class is not found !");
            return null;
        }
    }

    public byte[] loadClazz(String classPath) {
        try {
            FileInputStream in = new FileInputStream(new File(classPath));
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int b;
            while((b = in.read()) != -1){
                baos.write(b);
            }
            in.close();
            return baos.toByteArray();
        } catch (Exception e) {
            System.out.println(e);
        }
        return null;
    }

    public String getClassPath(String className){
        for(String path : paths){
            if(className.contains(".")){
                className = className.replaceAll(".", File.separator);
            }
            String classPath = path + className + SUFFIX;
            File classFile = new File(classPath);
            if(classFile.exists()){
                return classPath;
            }
        }
        return null;
    }
}

2、解析xml文件

package cn.fjs;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

//解析xml文件,获取类和方法
public class DynamicDom {
    private static DocumentBuilderFactory dbFactory = null;
    private static DocumentBuilder db = null;
    private static Document document = null;  

    static{
        try {
            dbFactory = DocumentBuilderFactory.newInstance();
            db = dbFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }
    }  

    public Map<String,List<String>> getMethods(String fileName) throws SAXException, IOException{
        Map<String,List<String>> classes = new HashMap<String, List<String>>();
        document = db.parse(fileName);
        NodeList nList = document.getElementsByTagName("class");
        for(int i = 0 ; i<nList.getLength();i++){
            Node node = nList.item(i);
            Element ele = (Element)node;
            if(node.getNodeType() == Element.ELEMENT_NODE){
              String clazz = ele.getAttribute("name");
              List<String> methods = new ArrayList<String>();
              String method = ele.getElementsByTagName("method").item(0).getTextContent();
              methods.add(method);
              classes.put(clazz, methods);
            }
        }
        return classes;
    }
}

3、测试类:

package cn.fjs;

import java.util.List;
import java.util.Map;
import cn.fjs.DynamicClassLoader;
import cn.fjs.DynamicDom;

public class DynamicClassLoaderTest {
    public static void main(String[] args) {
        DynamicDom dmo = new DynamicDom();//xml文件解析类
        Map<String, List<String>> classes;
        //重载ClassLoader类
        DynamicClassLoader loader = new DynamicClassLoader(new String[]{"D:\\tmp\\"});
        try {
            classes = dmo.getMethods("D:\\tmp\\a.xml");
            for(String key:classes.keySet()){
                for(String clazz : classes.get(key)){
                    Class<?> c =loader.findClass(key);//类名字
                    c.getMethod(clazz).invoke(c.newInstance());//方法名字
                }
            }
        }catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

执行结果:

 hello ...
1+1=2

原文地址:https://www.cnblogs.com/zhao1949/p/9700159.html

时间: 2024-11-07 20:16:26

Java运行时动态加载类之ClassLoader的相关文章

java 反射机制与动态加载类学习要点

获取Class类的对象: 假设Foo是一个类,Foo foo = new Foo():则 第一种:Class c1 = Foo.class; 第二种:Class c2 = foo.getClass(); 第三种:Class c3 = Class.forName("com.nudt.reflection.Foo"); //会抛出异常 此时  c1 == c2 == c3 为true 也可以通过c1\c2\c3创建Foo的实例: Foo foo = (Foo)c1.newInstance(

java动态加载类和静态加载类笔记

JAVA中的静态加载类是编译时刻加载类  动态加载类指的是运行时刻加载类 二者有什么区别呢 举一个例子  现在我创建了一个类  实现的功能假设为通过传入的参数调用具体的类和方法 class office { public static void main(String args[]) { if("word".equals(args[0]) { word w=new word(); word.run(); } if("excel".equals(args[0]) {

Java动态加载类

详见:https://blog.csdn.net/zai_xia/article/details/80026325 扩展:java反射机制与动态加载类 https://www.cnblogs.com/wzk-0000/p/9322866.html 在讲解动态加载类之前呢,我们先弄清楚为什么要动态加载类,静态加载不行吗?我们可以看下面的实例: 我在文件夹里写了Office.java 类和 Word.java类,如下: Office.java class Office{ public static

Java反射第二课 动态加载类

在第一节课中我们讲的第三种方法 Class.forName("类的全称"); 不仅表示了类的类类型,还代表了动态加载类 请大家区分编译,运行 编译时刻加载类是静态加载类,运行时刻加载类是动态加载类 现在的开发工具比如eclipse把编译过程给隐藏了 下面做一个实验 比如用记事本编写下面的Office.java文件 class Office { public static void main(String[] args) { if(("Word").equals(ar

Java 反射理解(二)-- 动态加载类

Java 反射理解(二)-- 动态加载类 概念 在获得类类型中,有一种方法是 Class.forName("类的全称"),有以下要点: 不仅表示了类的类类型,还代表了动态加载类 编译时刻加载类是静态加载类,运行时刻加载类是动态加载类 演示 我们以具体的代码来演示什么是动态加载类和静态加载类: 新建:Office.java: class Office { public static void main(String[] args) { // new 创建对象,是静态加载类,在编译时刻就需

Java 从Jar文件中动态加载类

由于开发的需要,需要根据配置动态加载类,所以简单测试了一下JAVA动态加载类 定义接口 package loader; public interface HelloIface {     public String hello();          public String sayHi(); } 实现接口 在其他插件类实现此接口,并导出为jar,如D:/tmp/test.jar package loader; public class HelloImpl implements HelloIf

Java-反射之动态加载类

在Java当中,加载类分为动态加载和静态加载,其中,在编译时刻加载类叫做静态加载类,在运行时刻加载类叫做动态加载类. 产生Class对象的方式中,有一个是Class.forName("类的全称"),这个不仅仅表示类的类类型,而且还表示了动态加载类. 1 package com.example.demo; 2 3 public class Demo { 4 public static void main(String[] args) { 5 if (args[0].equals(&quo

[javaSE] 反射-动态加载类

Class.forName(“类的全称”) ①不仅表示了类的类类型,还代表了动态加载类 ②请大家区分编译,运行 ③编译时刻加载类是静态加载类,运行时刻加载类是动态加载类 Ⅰ所有的new对象都是静态加载类 在编译的时刻就要去检测该类是否存在,如果不存在,编译失败. //对于这种情况,静态加载不适用,因为我们需要根据输入来确定加载哪个类 package com.tsh.reflect; class ReflectLoadDemo { public static void main(String[]

tomcat 5.5 动态加载类

转载于:http://www.itxuexiwang.com/a/javadianzishu/tomcat/2016/0225/161.html?1456480735 开发使用的是tomcat5.5.27,对于WEB-INF/classes下面的类做了修改,tomcat就会就会自动重启,然后紧接着就是内存溢出.调试比较麻烦.昨天研究了一下tomcat的源代码,对类的加载机制作了一点点修改,让它动态加载类,这样调试的时候如果修改了java文件就不用重启 tomcat了.具体步骤如下: 修改Weba