动态加载jar,实现自定义业务

Posted malaya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态加载jar,实现自定义业务相关的知识,希望对你有一定的参考价值。

在实际业务中,我们经常会遇到需要按不同用户实现不同业务逻辑,如果按照最简单粗暴的做法,当然是使用if else ...来实现。

不过作为一个社会人,这样怎么能体现出我们的战斗力呢,下面我们来实现一个牛叉的方法。

具体思路:

将不同的业务逻辑按用户放到不同的jar包,然后系统通过读取jar包,来实现各自业务;

以后即使用户的逻辑发生变化,也只要把jar包上传到服务器,就可以动态实现,不影响生产环境了。

1.接口

public interface InterfaceAction {

    public String getId();

    public abstract String action();
}

 

2.新建项目

action.ext.bj

pom.xml 依赖于base包

<dependency>
            <groupId>com.qn</groupId>
            <artifactId>action.base</artifactId>
            <version>0.0.1-SNAPSHOT</version>
</dependency>

 实现接口

public class ExtBj implements InterfaceAction {

    /** 
     * @see action.base.code.InterfaceAction#getId()
     */
    @Override
    public String getId() {
        return "bj";
    }

    /** 
     * @see action.base.code.InterfaceAction#action()
     */
    @Override
    public String action() {
        return "This is bj....";
    }

}

按照此项目新建个action.ext.nt

实现完接口后,导出jar包,存放到一个目录下;

 

3.完成自定义MyClassLoader

public class MyClassLoader {

    private ClassLoader                  loader;

    private Map<String, InterfaceAction> actionMap = new HashMap<>();

    /**
     * Getter method for property <tt>actionMap</tt>.
     * 
     * @return property value of actionMap
     */
    public Map<String, InterfaceAction> getActionMap() {
        return actionMap;
    }

    /**
     * Setter method for property <tt>actionMap</tt>.
     * 
     * @param actionMap value to be assigned to property actionMap
     */
    public void setActionMap(Map<String, InterfaceAction> actionMap) {
        this.actionMap = actionMap;
    }

    public void load(String jarFileName) {
        JarFile jarFile = null;
        try {
            File file = new File(jarFileName);
            URL url = new URL("file:" + jarFileName);
            loader = new URLClassLoader(new URL[] { url });

            file.lastModified();
            jarFile = new JarFile(file);
            Enumeration<JarEntry> enumFiles = jarFile.entries();
            JarEntry entry;
            //遍历Jar包中的每一个文件
            while (enumFiles.hasMoreElements()) {
                entry = enumFiles.nextElement();
                String classFullName = entry.getName();
                //仅处理.class文件
                if (classFullName.indexOf("META-INF") < 0 && classFullName.indexOf(".class") > 0) {
                    String className = classFullName.substring(0, classFullName.length() - 6)
                        .replaceAll("/", ".");
                    //使用当前类加载器加载jar包中的类
                    System.out.println("加载类start:" + className);
                    Class<?> clazz = loader.loadClass(className);
                    System.out.println("加载类end:" + clazz);
                    boolean flag = isInterface(clazz, InterfaceAction.class);
                    if (flag) {
                        InterfaceAction ia = ((Class<InterfaceAction>) clazz).newInstance();
                        actionMap.put(ia.getId(), ia);
                        System.out.println(actionMap);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 是否实现该接口
     * @param c
     * @param szInterface
     * @return
     */
    private boolean isInterface(Class c, Class szInterface) {
        Class[] face = c.getInterfaces();
        for (int i = 0, j = face.length; i < j; i++) {
            if (face[i].equals(szInterface)) {
                return true;
            }
        }
        return false;
    }
}

 

4.接下来就是test了

 public static void main(String[] args) {
        MyClassLoader ml = new MyClassLoader();
        ml.load("D:\\temp\\action.ext.bj.jar");
        ml.load("D:\\temp\\action.ext.nt.jar");
        String s = ml.getActionMap().get("nt").action();
        System.out.println(s);
    }
加载类start:action.ext.bj.ExtBj
加载类end:class action.ext.bj.ExtBj
{[email protected]}
加载类start:action.ext.nt.ExtNt
加载类end:class action.ext.nt.ExtNt
{[email protected], [email protected]}
This is nt.....

韦爵爷说过:大功告成。。。

 

以上是关于动态加载jar,实现自定义业务的主要内容,如果未能解决你的问题,请参考以下文章

使用URLClassLoader动态加载jar

从jar动态加载类

如何在模块化的 java 11 应用程序中动态加载 Libreoffice jar,而不从自定义类加载器中获取 ClassCastException

Springboot 使用@RefreshScope 注解,实现配置文件的动态加载

ClassLoader实现自定义类加载器加载指定路径下的Class文件和Jar包

ClassLoader实现自定义类加载器加载指定路径下的Class文件和Jar包