1. 程式人生 > >動態加載jar,實現自定義業務

動態加載jar,實現自定義業務

讀取 bool AR sta instance snapshot pub 加載 set

在實際業務中,我們經常會遇到需要按不同用戶實現不同業務邏輯,如果按照最簡單粗暴的做法,當然是使用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
{bj=action.ext.bj.ExtBj@5cd73256}
加載類start:action.ext.nt.ExtNt
加載類end:class action.ext.nt.ExtNt
{nt=action.ext.nt.ExtNt@6f580c3a, bj=action.ext.bj.ExtBj@5cd73256}
This is nt.....

韋爵爺說過:大功告成。。。

動態加載jar,實現自定義業務