zoukankan      html  css  js  c++  java
  • JNA&IOC实现反向动态调用不同dll版本

    @author:WMsteve
    @Email:weisteve@yeah.net
    @Time:2012年1月5日11:36:11
     
    现在项目中有一部分模型计算,交由一所高校进行合作开发,模型较为复杂。同时项目采用J2EE+Flex技术进行开发,模型开发采用Fortran语言,在项目集成过程中也带来很大的困惑。
    需求中需要主项目要提供模块的所需数据,同时需要接收模型的计算结果。
    模型后期需要不断改进,系统要求J2EE可以通过数据库的不同配置调用不同的DLL完成不同的模型预测。针对上述项目特色,需要解决两个方面的问题:
    1. J2EE成功调用DLL,并且可以对DLL进行复杂参数的传递;
    2. J2EE要能够根据不同的数据库配置参数,调用不同版本的DLL;
    针对第一个问题,目前可以通过JNI或者JNA两种方式来解决。
    JNI(Java Native Interface)是java平台一部分;
    JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射。
     
    以下是JNA官方介绍,附上能帮助理解。
    Java Native Access (JNA) has a single component, jna.jar; the supporting native library (jnidispatch) is included in the jar file. JNA is capable of extracting and loading the native library on its own, so you don't need additional configuration. JNA falls back to extraction if the native library is not already installed on the local system somwhere accessible to System.loadLibrary. The native library is also available in platform-specific jar files for use with Java Web Start.
    Begin by downloading the latest release of JNA and referencing jna.jar in your project's CLASSPATH.
    The following example maps the printf function from the standard C library and calls it. 
    给一个调用本地库的简单实例
    package com.wmcorp.modulemanager; 
    /***
     *@author:WMsteve
     *引入JNA所需库
     */

    import com.sun.jna.Native;
    import com.sun.jna.Platform;
    import com.sun.jna.Library;

    public class JNA_Printf {
        private static String DLLFileName="WMsteveDLL";

        public static void setDLLFileName(String FileName)
        {
            DLLFileName=FileName;
        }
        public interface CLibrary extends Library
        {
            CLibrary INSTANCE=(CLibrary)Native.loadLibrary((Platform.isWindows()?DLLFileName:"c"),CLibrary.class);

            int add(int a,int b);
        }
        /**
         * Method main
         *
         *
         * @param args
         *
         */


         
        public static void main(String[] args) {
            // TODO: Add your code here
            System.out.println(String.valueOf(CLibrary.INSTANCE.add(4,7)));
        }
    }
    看到上述代码,类JNA_Printf是一个java类,其中定义了内部接口CLibrary;接口内部首先声明了一个静态变量INSTANCE,通过这个load对应的dll。
    后面的是接口内函数声明:
     
    int add(int a,int b);
    同理所有dll中需要java调用的函数,均需要在这个接口中声明;
    上述函数在WMsteveDLL中的代码如下:
     
    extern "C" _declspec(dllexport) int add(int i,int j){ 
        return i+j;
    }
    上述类编译运行输出结果:11
    Note:
    如果您仔细看上面代码会有疑虑:
     
    private static String DLLFileName="WMsteveDLL";
    上述代码起到什么作用?
    能否通过更改文件名完成动态DLL库的加载?
    答案是错误的,这个DLL加载只能是静态加载,不能动态加载,上述代码仅是测试所用。
     
     
    针对第二个问题,需要利用IOC对针对同一接口再实现多态。
    设计UML图:
    上述设计中:
    IPredicate:模型接口;
    APredicate:模型的抽象类;
    PredicateA、PredicateB、PredicateC:预报的具体三个DLL对应的适配类;
    PredicateFactory:模型的生产工厂;
    CLibrary:JNA对应每个适配类的内部静态接口;
    ModuleManager:模型的管理类
     
    具体代码如下:(测试程序中PredicateA对应的是moduleA)
     
    PredicateFactory
     
    package com.wmcorp.modulemanager; 
    /***
     *@author:WMsteve
     *创建模块的工厂类
     */

    public class PredicateFactory {

        /**
         * Method PredicateFactory
         *
         *
         */

        public PredicateFactory() {
            // TODO: Add your code here
        }
        public static APredicate getClassByName(String instanceName)
        {
            Class cls=IocUtils.getClassByName(instanceName);
            //System.out.println(class.get);
            return (APredicate)IocUtils.getClassInstanceByClass(cls);
        }
    }
     
    IocUtils
     
    package com.wmcorp.modulemanager; 
    /***
     *IOC控制反转的公共函数
     */

    import java.lang.reflect.*;
    public final class IocUtils {

        /**
         * Method IocUtils
         *
         *
         */

        public IocUtils() {
            // TODO: Add your code here
        }

        /***
         *根据类名,通过反射提取class
         */

        public static Class getClassByName(String ClassName)
        {
            Class cls=null;
            try
            {
                cls = Class.forName(ClassName);
                //System.out.println("load the target class");
                //obj=(ACalculateModule)cls.newInstance();
                /*
                Class partypes[] = new Class[2];
                partypes[0] = Integer.TYPE;
                partypes[1] = Integer.TYPE;
                Method meth = cls.getMethod("add", partypes);
                System.out.println("get method of the class");
                Object arglist[] = new Object[2];
                arglist[0] = new Integer(37);
                arglist[1] = new Integer(47);
                */

                //object retobj = meth.invoke(methobj, arglist);
                //Object retobj = meth.Invoke(cls.newinstance(null), arglist);
                //Integer retval = (Integer)retobj;
                //System.out.println(retval.intValue());
            }
            catch(Exception e)
            {
                System.err.println(e);
            }
            return cls;
        }
        public static Object getClassInstanceByClass(Class cls)
        {
            Object obj=null;
            try
            {
                //cls = Class.forName(mName);
                //System.out.println("load the target class");
                obj=cls.newInstance();
                /*
                Class partypes[] = new Class[2];
                partypes[0] = Integer.TYPE;
                partypes[1] = Integer.TYPE;
                Method meth = cls.getMethod("add", partypes);
                System.out.println("get method of the class");
                Object arglist[] = new Object[2];
                arglist[0] = new Integer(37);
                arglist[1] = new Integer(47);
                */

                //object retobj = meth.invoke(methobj, arglist);
                //Object retobj = meth.Invoke(cls.newinstance(null), arglist);
                //Integer retval = (Integer)retobj;
                //System.out.println(retval.intValue());
            }
            catch(Exception e)
            {
                System.err.println(e);
            }
            return obj;
        }
    }
     
    moduleA
     
    package com.wmcorp.modulemanager.modules.moduleA; 
    import com.sun.jna.Native;
    import com.sun.jna.Platform;
    import com.sun.jna.Library;
    import com.wmcorp.modulemanager.*;

    //import APredicate;
    /***
     *@author:WMsteve
     *实体模型一
     *通过IOC反转控制静态接口CLibrary,调用不同DLL实现不同的模型预报
     */

    public class moduleA extends APredicate{
        public interface CLibrary extends Library
        {
            CLibrary INSTANCE=(CLibrary)Native.loadLibrary((Platform.isWindows()?"WMsteveDLL":"c"),CLibrary.class);
            int add(int a,int b);
        }
        /**
         * Method moduleA
         *
         *
         */

        public moduleA() {
            // TODO: Add your code here
            WMUID="I'm moduleA!";
        }

        /**
         * Method WMoperate1
         *
         *
         * @param str
         *
         * @return
         *
         */

        public String WMoperate1(String str) {
            // TODO: Add your code here
            return String.valueOf(CLibrary.INSTANCE.add(4,7));
        }
    }
     
    moduleB
     
    package com.wmcorp.modulemanager.modules.moduleB; 
    import com.sun.jna.Native;
    import com.sun.jna.Platform;
    import com.sun.jna.Library;
    import com.wmcorp.modulemanager.*;

    public final class moduleB extends APredicate{
        public interface CLibrary extends Library
        {
            CLibrary INSTANCE=(CLibrary)Native.loadLibrary((Platform.isWindows()?"WMsteveSUB":"c"),CLibrary.class);
            int add(int a,int b);
        }
        /**
         * Method moduleB
         *
         *
         */

        public moduleB() {
            // TODO: Add your code here
            WMUID="I'm moduleB!";
        }

        /**
         * Method WMoperate1
         *
         *
         * @param str
         *
         * @return
         *
         */

        public String WMoperate1(String str) {
            // TODO: Add your code here
            return String.valueOf(CLibrary.INSTANCE.add(4,7));
        }
    }
     
    测试代码
     
    public class JNA_IOC { 
        public JNA_IOC() {
        }
        public static void main(String[] args) {
            APredicate ap=PredicateFactory.getClassByName("com.wmcorp.modulemanager.modules.moduleB.moduleB");
            System.out.println(ap.WMoperate1("wm"));
            // TODO: Add your code here
            //JNA_Printf jna_printf=new JNA_Printf();
            //System.out.printf("%d\n",JNA_Printf.CLibrary.INSTANCE.add(1,7));
            //JNA_Printf.CLibrary.changeFile("WMsteveSub");
            //System.out.printf("%d\n",JNA_Printf.CLibrary.INSTANCE.add(1,7));
            //System.out.printf("sdf");
            //CLibrary.INSTANCE.printf("hello world\n");
        }
    }



     

    作者:W.M.steve
    出处:http://www.cnblogs.com/weisteve/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    如何关闭和打开oracle 10g自动收集统计信息功能
    ORA00600:internal error code,arguments
    ORA01033: ORACLE initialization or shutdown in progress
    ORA01652:unable to extend temp segment by num in tablespace name
    ORA01578:Oracle data block corrupted
    ORA03113:endoffile on communication channel
    ORA01650:unable to extend rollback segment NAME by NUM intablespace NAME
    ORA01628:max # of extents num reached for rollback segment num
    C# 项目中的 bin 目录和 obj 目录的区别,以及 Debug 版本和 Release 版本的区别
    管理 Hadoop 集群的5大工具
  • 原文地址:https://www.cnblogs.com/weisteve/p/2313130.html
Copyright © 2011-2022 走看看