Java 动态的创建注入代码,注入方法给类或者接口并通过反射调用

1、将要被注入的类:

/*
 * 文 件 名:  JNAUtil.java
 * 版    权:  Sunny Technologies Co., Ltd. Copyright YYYY-YYYY,  All rights reserved
 * 描    述:  <描述>
 * 修 改 人:  L.Hao
 * 修改时间:  2014-11-11
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.test;																					

import java.util.Arrays;
import java.util.List;																					

import com.fms.xx.model.ParamBean;
import com.sun.jna.Native;																					

/**
 * <一句话功能简述>
 * <功能详细描述>
 *
 * @author  L.Hao
 * @version  [版本号, 2014-11-11]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class JNAUtil
{
    //Dll文件路径
    public String filePath ;																					

    public JNAUtil(String filePath)
    {
        this.filePath = filePath;
    }																					

public double[] XT(List<ParamBean> parameterList, double[] arr)
{
  CLibrary INSTANCE = (CLibrary)Native.loadLibrary(filePath,CLibrary.class);
  int num = 0;
  INSTANCE.XT(  Double.valueOf(parameterList.get(num++).getParamValue()),
  Double.valueOf(parameterList.get(num++).getParamValue()),
  Double.valueOf(parameterList.get(num++).getParamValue()),
  arr);
  return arr;
}
}

2、将要被注入的接口

/*
\ * 文 件 名:  CLibrary.java
 * 版    权:  Sunny Technologies Co., Ltd. Copyright YYYY-YYYY,  All rights reserved
 * 描    述:  <描述>
 * 修 改 人:  L.Hao
 * 修改时间:  2014-11-11
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.test;																																		

import com.sun.jna.Library;																																		

/**
 * <一句话功能简述>
 * <功能详细描述>
 *
 * @author  L.Hao
 * @version  [版本号, 2014-11-11]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public interface CLibrary extends Library
{																								

   public void XT(double FLJ,double XTT,double FLK,double ARR[]);
}

3,注入动态代码并调用

/*
 * 文 件 名:  WriteJavaFile.java
 * 版    权:  Sunny Technologies Co., Ltd. Copyright YYYY-YYYY,  All rights reserved
 * 描    述:  <描述>
 * 修 改 人:  L.Hao
 * 修改时间:  2014-11-15
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;

import com.fms.xx.common.FunctionParam;
import com.fms.xx.model.ParamBean;

/**
 * 写Java文件
 * <功能详细描述>
 *
 * @author  L.Hao
 * @version  [版本号, 2014-11-15]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class WriteJavaFile
{
    private static String filePath = "F:\\Workspaces\\MyEclipse10\\xxcalculate\\src\\com\\test\\CLibrary.java";

    private static String filePath_JNAUtil = "F:\\Workspaces\\MyEclipse10\\xxcalculate\\src\\com\\test\\JNAUtil.java";

    private static String CHFile = "F:\\soft\\apache-tomcat-7.0.52\\webapps\\xxcalculate\\upload\\141112212749\\SharedLib.h";

    /** <一句话功能简述>
     * <功能详细描述>
     * @param args [参数说明]
     *
     * @return void [返回类型说明]
     * @throws Exception
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static void main(String[] args) throws Exception
    {
        //当前类的路径
        System.out.println("当前类的路径:"+new File("").getAbsolutePath());
        //创建文件
        createFile(filePath);
        //读接口CLibrary文件
        String cLibraryFileContent = readFile(filePath);

        List<FunctionParam> params = parseHfile(CHFile);
        //待拼接的内容
        String appendContent = spliceCLibraryString(params);
        //写文件(如果已经存在就不拼接了)
        if(!cLibraryFileContent.trim().replaceAll("\\s*", "").contains(appendContent.trim().replaceAll("\\s*", ""))){
            WriteStringToFile(filePath, cLibraryFileContent, appendContent);
        }

        //读接口JNAUtil文件
        String jNAUtilFileContent = readFile(filePath_JNAUtil);

        appendContent = spliceJNAUtilString(params);
        //写文件(如果已经存在就不拼接了)
        if(!jNAUtilFileContent.trim().replaceAll("\\s*", "").contains(appendContent.trim().replaceAll("\\s*", ""))){
            WriteStringToFile(filePath_JNAUtil, jNAUtilFileContent, appendContent);
        }

        String filePath = "F:\\Workspaces\\MyEclipse10\\xxcalculate\\src\\com\\test";
        String sourceDir = "F:\\Workspaces\\MyEclipse10\\xxcalculate\\src\\com\\test";
        String targetDir = "F:\\soft\\apache-tomcat-7.0.52\\webapps\\xxcalculate\\WEB-INF\\classes";

        boolean result = compiler(filePath, sourceDir, targetDir);
        List<ParamBean> parames = new ArrayList<ParamBean>();
        //ParamBean(String paramCode, String paramName, String paramValue, String paramType)
        parames.add(new ParamBean("FLJ", "空气密度", "0.42", "double"));
        parames.add(new ParamBean("XTT", "空气密度", "0.3", "double"));
        parames.add(new ParamBean("FLK", "空气密度", "0.2", "double"));
        double[] arr = new double[4];
        //编译成功,开始计算
        if (result)
        {
            reflectCall(parames,arr);
        }
    }

    /**
     * 反射调用生成的文件
     * <功能详细描述>
     * @param parames
     * @param arr [参数说明]
     *
     * @return void [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static void reflectCall(List<ParamBean> parames, double[] arr)
    {
        try
        {
            Constructor<?> conststr = Class.forName("com.test.JNAUtil")
                    .getDeclaredConstructor(new Class[] { String.class });
            conststr.setAccessible(true);
            Object bl = conststr.newInstance(new Object[] { "F:\\soft\\apache-tomcat-7.0.52\\webapps\\xxcalculate\\upload\\141112212749\\SharedLib.dll" });

            Class<? extends Object> clazz = bl.getClass();

            Method method = clazz.getDeclaredMethod("XT",
                    List.class,
                    double[].class);

            method.invoke(bl, parames, arr);
            System.out.println("计算结果:" + Arrays.toString(arr));
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    // 创建单个文件
    public static boolean createFile(String filePath)
    {
        File file = new File(filePath);
        if (file.exists())
        {// 判断文件是否存在
            System.out.println("目标文件已存在" + filePath);
            //file.delete();
            return false;
        }
        if (filePath.endsWith(File.separator))
        {// 判断文件是否为目录
            System.out.println("目标文件不能为目录!");
            return false;
        }
        if (!file.getParentFile().exists())
        {// 判断目标文件所在的目录是否存在
         // 如果目标文件所在的文件夹不存在,则创建父文件夹
            System.out.println("目标文件所在目录不存在,准备创建它!");
            if (!file.getParentFile().mkdirs())
            {// 判断创建目录是否成功
                System.out.println("创建目标文件所在的目录失败!");
                return false;
            }
        }
        try
        {
            if (file.createNewFile())
            {// 创建目标文件
                System.out.println("创建文件成功:" + filePath);
                return true;
            }
            else
            {
                System.out.println("创建文件失败!");
                return false;
            }
        }
        catch (IOException e)
        {// 捕获异常
            e.printStackTrace();
            System.out.println("创建文件失败!" + e.getMessage());
            return false;
        }
    }

    /**
     * 读取指定文件的内容
     * 将指定文件的内容读入到StringBuffer中
     * @param filePath
     * @return [参数说明]
     *
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String readFile(String filePath)
    {
        File file = new File(filePath);
        BufferedReader reader = null;
        StringBuffer sb = new StringBuffer();
        try
        {
            //System.out.println("以行为单位读取文件内容,一次读一整行:");
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            //int line = 1;
            // 一次读入一行,直到读入null为文件结束
            while ((tempString = reader.readLine()) != null)
            {
                sb.append(tempString).append("\t\n");

            }
            reader.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return sb.toString();
    }

    /**
     * 将字符串写入指定文件
     * 在已有文件内容的基础上写入新内容
     * @param filePath  文件路径
     * @param oldContent 已有内容
     * @param newContent 新加内容
     *
     * @return void [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static void WriteStringToFile(String filePath, String oldContent,
            String newContent)
    {
        StringBuffer strBuffer = new StringBuffer();
        try
        {
            oldContent = oldContent.substring(0, oldContent.lastIndexOf("}"));
            strBuffer.append(oldContent);
            strBuffer.append(newContent);
            strBuffer.append("}");
            // 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
            FileWriter writer = new FileWriter(filePath, false);
            writer.write(strBuffer.toString());
            writer.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 文件编译
     * 调用java编译器编译java文件
     * @param filePath  文件路径
     * @param sourceDir 源文件所在目录
     * @param targetDir 目标文件所在目录
     *
     * @return boolean [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    @SuppressWarnings("rawtypes")
    public static boolean compiler(String filePath, String sourceDir,
            String targetDir)
    {
        boolean compilerResult = false;
        try
        {
            DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
            compilerResult = DynamicCompilerUtil.compiler(filePath,
                    sourceDir,
                    targetDir,
                    diagnostics);
            if (compilerResult)
            {
                System.out.println("编译成功");
            }
            else
            {
                System.out.println("编译失败");
                for (Diagnostic diagnostic : diagnostics.getDiagnostics())
                {
                    System.out.println(diagnostic.getMessage(null));
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return compilerResult;
    }

    /**
     * <一句话功能简述>
     * <功能详细描述>
     * @param fileName
     * @return [参数说明]
     *
     * @return List<FunctionParam> [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static List<FunctionParam> parseHfile(String fileName)
    {
        Map<String, List<FunctionParam>> map = ReadHFile.parseH(fileName);

        List<FunctionParam> params = (List<FunctionParam>) map.get("params");

        return params;
    }

    /**
     * 拼接接口文件内容
     * <功能详细描述>
     * @param params
     * @return [参数说明]
     *
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String spliceCLibraryString(List<FunctionParam> params)
    {
        StringBuffer strBuffer = new StringBuffer();
        strBuffer.append("   public void ");
        strBuffer.append(params.get(0).getMethodName()).append("(");
        for (FunctionParam functionParam : params)
        {
            strBuffer.append(functionParam.getParamType())
                    .append(" ")
                    .append(functionParam.getParamName())
                    .append(",");
        }
        strBuffer.replace(strBuffer.length() - 1, strBuffer.length(), "");
        strBuffer.append(");").append("\t\n");
        return strBuffer.toString();
    }

    /**
     * 拼接被调用类内容
     * <功能详细描述>
     * @param params
     * @return [参数说明]
     *
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String spliceJNAUtilString(List<FunctionParam> params)
    {
        String methodName = params.get(0).getMethodName();
        StringBuffer strBuffer = new StringBuffer();
        strBuffer.append("public double[] ");
        strBuffer.append(methodName)
                .append("(List<ParamBean> parameterList, double[] arr)")
                .append("\t\n");
        strBuffer.append("{").append("\t\n");
        strBuffer.append(" CLibrary INSTANCE = (CLibrary)Native.loadLibrary(filePath,CLibrary.class);")
                .append("\t\n");
        strBuffer.append("  int num = 0;").append("\t\n");
        strBuffer.append("  INSTANCE.").append(methodName).append("(");

        int count = params.size();

        int num = 0;
        for (FunctionParam functionParam : params)
        {
            num++;
            if (count == num)
            {
                continue;
            }
            if ("double".equalsIgnoreCase(functionParam.getParamType()))
            {
                strBuffer.append("    Double.valueOf(parameterList.get(num++).getParamValue()),")
                        .append("\t\n");
            }
            if ("char".equalsIgnoreCase(functionParam.getParamType()))
            {
                strBuffer.append("    parameterList.get(num++).getParamValue().toCharArray(),")
                        .append("\t\n");
            }
        }
        strBuffer.append("  arr);").append("\t\n");
        strBuffer.append("  return arr;").append("\t\n");
        strBuffer.append("}").append("\t\n");
        return strBuffer.toString();
    }
}
时间: 2024-10-18 20:18:21

Java 动态的创建注入代码,注入方法给类或者接口并通过反射调用的相关文章

Android开发中,那些让你觉得相见恨晚的方法、类或接口

本篇文章内容提取自知乎android开发中,有哪些让你觉得相见恨晚的方法.类或接口?,其实有一部是JAVA的,但是在android开发中也算常见.大多数的函数自己还是见过的,这里记录一下备忘.同时呢,也推荐一个github项目,里面记录了自己日常开发中见过的比较有用的东西开发中常用的工具.链接 Throwable类中的getStackTrace()方法,根据这个方法可以得到函数的逐层调用地址,其返回值为StackTraceElement[],而在StackTraceElement类中有四个方法g

java语言实现创建型设计模式—工厂方法模式

一.描述 基于简单工厂模式中将所有类的创建和初始化放在一个工厂类中出现的问题,我们引进了工厂方法模式,该模式是GoF总结的23种设计模式的第一种,这个设计模式将一个工厂类拆分成多个具体的工厂类,每个具体的工厂类负责相应的类的对象的创建. 在工厂方法模式中,抽象工厂类负责定义创建对象的接口,具体对象的创建由实现该抽象工厂的具体工厂类来完成,它由四部分组成:抽象工厂类.实现抽象工厂类的具体工厂类.抽象类.实现抽象类的具体类. 二.工厂方法模式的优缺点 优点:在工厂方法模式中,创建对象的任务由具体的工

Java设计模式(创建型:工厂方法模式+抽象工厂模式)

设计模式根据目的准则可以分为三类: 创建型:creational 创建型的设计模式与对象的创建有关. 结构型:Structural 处理类和对象之间的组合. 行为型:behavioral 描述类和对象如何交互及如何分配职责. 工厂方法模式 站在使用者的角度,工厂方法模式是指使用者提出想要实现的具体功能或者说是想要生产的具体的东西的要求,在通过工厂制造之后就将该东西或功能交付给使用者.使用者并不知道实现的具体过程,只是做了要求提出以及实现的结果的使用. 严谨来说工厂方法模式(Factory Met

Android开发中,有哪些让你觉得相见恨晚的方法、类或接口?

Activity.startActivities() 常用于在应用程序中间启动其他的Activity.TextUtils.isEmpty() 简单的工具类,用于检测是否为空.Html.fromHtml() 用于生成一个Html,参数可以是一个字符串.个人认为它不是很快,所以我不怎么经常去用.(我说不经常用它是为了重点突出这句话:请多手动构建 Spannable 来替换 Html.fromHtml),但是它对渲染从 web 上获取的文字还是很不错的.TextView.setError() 在验证用

Android开发中,一些相见恨晚的方法、类或接口

1.Throwable接口中的getStackTrace()方法,根据这个方法可以得到函数的逐层调用地址,其返回值为StackTraceElement[]: 2.StackTraceElement类,其中四个方法getClassName(),getFileName(),getLineNumber(),getMethodName()在调试程序打印Log时非常有用: 3.UncaughtExceptionHandler接口,再好的代码异常难免,利用此接口可以处理未捕获的异常: 4.View中的isS

【Simple Java】Java中怎样创建线程安全的方法

面试问题: 下面的方法是否线程安全?怎样让它成为线程安全的方法? class MyCounter { private static int counter = 0; public static int getCount() { return counter++; } } 本篇文章将解释一个常见的面试题,该问题被谷歌和很多其它公司问起过.它涉及的相对比较初级,而不是关于怎样去设计复杂的并发程序. 首先,这个问题的答案是No,因为counter++操作不是一个原子操作,而是由多个原子操作组成. 举个

Java设计模式(创建型:工厂方法模式)

(该文内容为原创,有不足之处望多多指教!) 设计模式根据目的准则可以分为三类: 创建型:creational 创建型的设计模式与对象的创建有关. 结构型:Structural 处理类和对象之间的组合. 行为型:behavioral 描述类和对象如何交互及如何分配职责. 工厂方法模式是什么? 站在使用者的角度,工厂方法模式是指使用者提出想要实现的具体功能或者说是想要生产的具体的东西的要求,在通过工厂制造之后就将该东西或功能交付给使用者.使用者并不知道实现的具体过程,只是做了要求提出以及实现的结果的

java获取资源路径的代码(方法简单 每次都遗忘 备注一下)

//通过java类获取 类名.class.getResource("/").getPath() + "文件名" 例子:HttpConnectionUtil.class .getResource("/").getPath() + "cas-service.properties" //request获取 request.getRealPath("WEB-INF/cas-service.properties")

27 Java动态加载第三方jar包中的类

我加载的方法是://参数fileName是jar包的路径,processorName 是业务类的包名+类名public static A load(String fileName, String processorName) {            String filePath = fileName;              A processor = null;  URL url;try {  url = new URL(filePath);} catch (MalformedURLEx