English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

مثال على تفاعل برمجة Java الديناميكية

في بعض الحالات، نحتاج إلى إنشاء كود جافا ديناميكي، ثم ترميزه ديناميكيًا، وأخيرًا تنفيذ الكود. يقدم API الخاص بجافا أدوات مطلوبة (JavaCompiler) لتحقيق الترميز الديناميكي. فيما يلي، نقدم مثالًا بسيطًا يوضح كيفية تحقيق الترميز الديناميكي للكود باستخدام JavaCompiler.

الجزء الأول: الحصول على JavaCompiler

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

الحصول على مسبق التزويد من JDK للمدقق java، وإذا لم يتم تزويده، يتم العودة إلى null؛

الجزء الثاني: التجميع

//الحصول على فئة إدارة ملفات java
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
//الحصول على معادلة ملفات java
Iterable<? extends JavaFileObject> it = manager.getJavaFileObjects(files);
//تعيين معلمات الترميم
ArrayList<String> ops = new ArrayList<String>();
ops.add("-Xlint:unchecked");
//تعيين classpath
ops.add("-classpath");
ops.add(CLASS_PATH);
//الحصول على مهمة التجميع
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, ops, null, it);
//تنفيذ مهمة التجميع
task.call();

عندما نريد تجميع ملفات المصدر التي تم استيرادها، يجب تعيين مسار الاستيراد إلى -classpath، وإلا سيتم فشل التجميع.

الجزء الثالث: التنفيذ

//اسم الفئة التي سيتم تحميلها
String className = "xxx.xxx.xxx";
//الحصول على محمل الفئات
ClassLoader classLoader = XXX.class.getClassLoader();
//تحميل الفئة
Class<?> cls = classLoader.loadClass(className);
//اسم الدالة التي سيتم تقديمها
String methodName = "execute";
//مجموعة أنواع الم 参数
Class<?>[] paramCls = {...};
//الحصول على الدالة
Method method = cls.getDeclaredMethod(methodName , paramCls);
//إنشاء مثيل للفئة
Object obj = cls.newInstance();
//م参数
Object[] params = {...};
//تقديم الدالة
Object result = method.invoke(obj, params);

الجزء الرابع: الكود الكامل

//ClassUtil.java
استيراد java.io.FileWriter;
استيراد java.io.BufferedWriter;
استيراد java.io.File;
استيراد java.io.IOException;
استيراد java.util.ArrayList;
استيراد javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ClassUtil {
	private static final Log logger = LogFactory.getLog(ClassUtil.class);
	private static JavaCompiler compiler;
	static{
		compiler = ToolProvider.getSystemJavaCompiler();
	}
	/**
   * الحصول على مسار ملف java
   * @param file
   * @return
   */
	private static String getFilePath(String file){
		int last1 = file.lastIndexOf('/');
		int last2 = file.lastIndexOf('\\');
		return file.substring(0, last1>last2?last1:last2)+File.separatorchar;
	}
	/**
   * تجميع ملفات java
   * @param ops معلمات التجميع
   * @param files ملفات التجميع
   */
	private static void javac(List<String> ops, String... files){
		StandardJavaFileManager manager = null;
		try{
			manager = compiler.getStandardFileManager(null, null, null);
			Iterable<? extends JavaFileObject> it = manager.getJavaFileObjects(files);
			JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, ops, null, it);
			task.call();
			if(logger.isDebugEnabled()){
				for (String file:files)
				          logger.debug("Compile Java File:" + file);
			}
		}
		catch(Exception e){
			logger.error(e);
		}
		finally{
			if(manager!=null){
				try {
					manager.close();
				}
				catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	/**
   * إنشاء ملف Java
   * @param file اسم الملف
   * @param source كود Java
   * @throws Exception
   */
	private static void writeJavaFile(String file,String source)throws Exception{
		if(logger.isDebugEnabled()){
			logger.debug("Write Java Source Code to:"+file);
		}
		BufferedWriter bw = null;
		try{
			File dir = new File(getFilePath(file));
			if(!dir.exists())
			        dir.mkdirs();
			bw = new BufferedWriter(new FileWriter(file));
			bw.write(source);
			bw.flush();
		}
		catch(Exception e){
			throw e;
		}
		finally{
			if(bw!=null){
				bw.close();
			}
		}
	}
	/**
   * تحميل الفئة
   * @param name اسم الفئة
   * @return
   */
	private static Class<?> load(String name){
		Class<?> cls = null;
		ClassLoader classLoader = null;
		try{
			classLoader = ClassUtil.class.getClassLoader();
			cls = classLoader.loadClass(name);
			if(logger.isDebugEnabled()){
				logger.debug("Load Class["+name+"] by "+classLoader);
			}
		}
		catch(Exception e){
			logger.error(e);
		}
		return cls;
	}
	/**
   * تجميع الكود وتحميل الفئة
   * @param filePath مسار كود Java
   * @param source كود Java
   * @param clsName اسم الفئة
   * @param ops معلمات التجميع
   * @return
   */
	public static Class<?> loadClass(String filePath,String source,String clsName,List<String> ops){
		try {
			writeJavaFile(CLASS_PATH+filePath,source);
			javac(ops,CLASS_PATH+filePath);
			return load(clsName);
		}
		catch (Exception e) {
			logger.error(e);
		}
		return null;
	}
	/**
   * دعوة أسلوب الفئة
   * @param cls فئة
   * @param methodName اسم الأسلوب
   * @param paramsCls نوعية أسلوب
   * @param params 参数 للأسلوب
   * @return
   */
	public static Object invoke(Class<?> cls,String methodName,Class<?>[] paramsCls,Object[] params){
		Object result = null;
		try {
			Method method = cls.getDeclaredMethod(methodName, paramsCls);
			Object obj = cls.newInstance();
			result = method.invoke(obj, params);
		}
		catch (Exception e) {
			logger.error(e);
		}
		return result;
	}
}

خامسًا، اختبار

public class ClassUtilTest {
	private static final Log logger = LogFactory.getLog(ClassUtilTest.class);
	public static void main(String args[]){
		StringBuilder sb = new StringBuilder();
		sb.append("package com.even.test;");
		sb.append("import java.util.Map;\nimport java.text.DecimalFormat;\n");
		sb.append("public class Sum{\n");
		sb.append("private final DecimalFormat df = new DecimalFormat(\"#.#####\");\n");
		sb.append("public Double calculate(Map<String,Double> data){\n");
		sb.append("double d = (30*data.get(\"f1\") + 20*data.get(\"f2\") + 50*data.get(\"f3\"))/100;\n");
		sb.append("return Double.valueOf(df.format(d));}}\n");
		//تعيين معلمات الترميم
		ArrayList<String> ops = new ArrayList<String>();
		ops.add("-Xlint:unchecked");
		//ترميم الكود، عودة class
		Class<?> cls = ClassUtil.loadClass("/com/even/test/Sum.java",sb.toString(),"com.even.test.Sum",ops);
		//إعداد بيانات الاختبار
		Map<String,double> data = new HashMap<String,double>();
		data.put("f1", 10.0);
		data.put("f2", 20.0);
		data.put("f3", 30.0);
		//إجراء اختبار الطريقة
		Object result = ClassUtil.invoke(cls, "calculate", new Class[]{Map.class}, new Object[]{data});
		//إخراج النتائج
		logger.debug(data);
		logger.debug("(30*f1+20*f2+50*f3)/100 = "+result);
	}

نتائج الاختبار

16:12:02.860 DEBUG com.even.tools.ClassUtil - Write Java Source Code to: .../classes//com/even/test/Sum.java
16:12:03.544 DEBUG com.even.tools.ClassUtil - Compile Java File:.../classes//com/even/test/Sum.java
16:12:03.545 DEBUG com.even.tools.ClassUtil - Load Class[com.even.test.Sum] by sun.misc.Launcher$AppClassLoader@73d16e93
16:12:03.547 DEBUG com.even.test.ClassUtilTest - {f1=10.0, f2=20.0, f3=30.0}
16:12:03.547 DEBUG com.even.test.ClassUtilTest - (30*f1+20*f2+50*f3)/100 = 22.0

الخلاصة

هذا هو محتوى المقال الكامل حول مثال التشغيل الديناميكي للترميز في Java، آمل أن يكون مفيداً لكم. يمكن للأصدقاء المهتمين الاستمرار في مراجعة هذا الموقع:

مشاركة شفرة التكوين الديناميكي لـ java

مثال على مشكلة المسافة التحريرية في التخطيط الديناميكي لـ Java

تفسير تفاصيل الاستدلال والوكلات الديناميكية في Java

يرجى ترك تعليق إذا كان هناك نقص، شكراً للأصدقاء على دعم هذا الموقع!

بيان: محتوى هذا المقال تم جمعه من الإنترنت، يحق لصاحب الحقوق أن يكون له حقوق ملكية، تم جمع المحتوى من قبل المستخدمين على الإنترنت الذين قدموا مساهماتهم الخاصة، ولا يملك هذا الموقع حقوق الملكية، لم يتم تعديل المحتوى بشكل يدوي، ولا يتحمل هذا الموقع أي مسؤولية قانونية ذات صلة. إذا كنت قد وجدت محتوى يشتبه في حقوق النسخ، فيرجى إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال # ب @) لتقديم الشكوى، وقدم الدليل على الشكوى، إذا تم التحقق من ذلك، سيقوم هذا الموقع بإزالة المحتوى المشبوه في حقوق النسخ.

توصياتك المفضلة