一级日韩免费大片,亚洲一区二区三区高清,性欧美乱妇高清come,久久婷婷国产麻豆91天堂,亚洲av无码a片在线观看

Java中的動(dòng)態(tài)代碼編程

時(shí)間:2024-06-27 15:06:03 JAVA認證 我要投稿
  • 相關(guān)推薦

Java中的動(dòng)態(tài)代碼編程

  Java不是解決動(dòng)態(tài)層問(wèn)題的理想語(yǔ)言,這些動(dòng)態(tài)層問(wèn)題包括原型設計、腳本處理等。

  公司的項目主要基于Java平臺,在實(shí)踐中發(fā)現主要有兩種方式可以實(shí)現:

  統一表達式語(yǔ)言

  動(dòng)態(tài)語(yǔ)言,如Groovy

  JUEL(Java 統一表達式語(yǔ)言)

  Java*統一表達式語(yǔ)言(英語(yǔ):Unified Expression Language,簡(jiǎn)稱(chēng)JUEL*)是一種特殊用途的編程語(yǔ)言,主要在Java Web應用程序用于將表達式嵌入到web頁(yè)面。Java規范制定者和Java Web領(lǐng)域技術(shù)專(zhuān)家小組制定了統一的表達式語(yǔ)言。JUEL最初包含在JSP 2.1規范JSR-245中,后來(lái)成為Java EE 7的一部分,改在JSR-341中定義。

  主要的開(kāi)源實(shí)現有:OGNL ,MVEL ,SpEL ,JUEL ,Java Expression Language (JEXL) ,JEval,Jakarta JXPath 等。這里主要介紹在實(shí)踐中使用較多的MVEL、OGNL和SpEL。

  OGNL(Object Graph Navigation Library)

  在Struts 2 的標簽庫中都是使用OGNL表達式訪(fǎng)問(wèn)ApplicationContext中的對象數據,OGNL主要有三個(gè)重要因素:

  Expression

  Expression是整個(gè)OGNL的核心內容,所有的OGNL操作都是針對表達式解析后進(jìn)行的。通過(guò)Expression來(lái)告知OGNL操作到 底要干些什么。因此,Expression其實(shí)是一個(gè)帶有語(yǔ)法含義的字符串,整個(gè)字符串將規定操作的類(lèi)型和內容。OGNL表達式支持大量 Expression,如“鏈式訪(fǎng)問(wèn)對象”、表達式計算、甚至還支持Lambda表達式。

  Root對象:

  OGNL的Root對象可以理解為OGNL的操作對象。當我們指定了一個(gè)表達式的時(shí)候,我們需要指定這個(gè)表達式針對的是哪個(gè)具體的對象。而 這個(gè)具體的對象就是Root對象,這就意味著(zhù),如果有一個(gè)OGNL表達式,那么我們需要針對Root對象來(lái)進(jìn)行OGNL表達式的計算并且返回結果。

  ApplicationContext

  有個(gè)Root對象和Expression,我們就可以使用OGNL進(jìn)行簡(jiǎn)單的操作了,如對Root對象的賦值與取值操作。但是,實(shí)際上在OGNL的 內部,所有的操作都會(huì )在一個(gè)特定的數據環(huán)境中運行。這個(gè)數據環(huán)境就是ApplicationContext(上下文環(huán)境)。OGNL的上下文環(huán)境是一個(gè) Map結構,稱(chēng)之為OgnlContext。Root對象也會(huì )被添加到上下文環(huán)境當中去。

  Foo foo = new Foo();foo.setName("test");Map context = new HashMap();context.put("foo",foo);String expression = "foo.name == 'test'";try {

  Boolean result = (Boolean) Ognl.getValue(expression,context);

  System.out.println(result);} catch (OgnlException e) {

  e.printStackTrace();}

  這段代碼就是判斷對象foo的name屬性是否為test。

  OGNL的具體語(yǔ)法參見(jiàn)OGNL language guide 。

  MVEL

  MVEL最初作為Mike Brock創(chuàng )建的 Valhalla項目的表達式計算器(expression evaluator)。Valhalla本身是一個(gè)早期的類(lèi)似 Seam 的“開(kāi)箱即用”的Web 應用框架,而 Valhalla 項目現在處于休眠狀態(tài), MVEL則成為一個(gè)繼續積極發(fā)展的項目。相比最初的OGNL、JEXL和JUEL等項目,而它具有遠超它們的性能、功能和易用性 – 特別是集成方面。它不會(huì )嘗試另一種JVM語(yǔ)言,而是著(zhù)重解決嵌入式腳本的問(wèn)題。

  MVEL特別適用于受限環(huán)境 – 諸如由于內存或沙箱(sand-boxing)問(wèn)題不能使用字節碼生成。它不是試圖重新發(fā)明Java,而是旨在提供一種Java程序員熟悉的語(yǔ)法,同時(shí)還加入了簡(jiǎn)短的表達式語(yǔ)法。

  MVEL主要使用在Drools,是Drools規則引擎不可分割的一部分。

  MVEL語(yǔ)法較為豐富,不僅包含了基本的屬性表達式,布爾表達式,變量復制和方法調用,還支持函數定義,詳情參見(jiàn)MVEL Language Guide 。

  MVEL在執行語(yǔ)言時(shí)主要有解釋模式(Interpreted Mode)和編譯模式(Compiled Mode )兩種:

  解釋模式(Interpreted Mode)是一個(gè)無(wú)狀態(tài)的,動(dòng)態(tài)解釋執行,不需要負載表達式就可以執行相應的腳本。

  編譯模式(Compiled Mode)需要在緩存中產(chǎn)生一個(gè)完全規范化表達式之后再執行。

  解釋模式

  //解釋模式Foo foo = new Foo();foo.setName("test");Map context = new HashMap();String expression = "foo.name == 'test'";VariableResolverFactory functionFactory = new MapVariableResolverFactory(context);context.put("foo",foo);Boolean result = (Boolean) MVEL.eval(expression,functionFactory);System.out.println(result);

  編譯模式

  //編譯模式Foo foo = new Foo();foo.setName("test");Map context = new HashMap();String expression = "foo.name == 'test'";VariableResolverFactory functionFactory = new MapVariableResolverFactory(context);context.put("foo",foo);Serializable compileExpression = MVEL.compileExpression(expression);Boolean result = (Boolean) MVEL.executeExpression(compileExpression, context, functionFactory);

  SpEL

  SpEl(Spring表達式語(yǔ)言)是一個(gè)支持查詢(xún)和操作運行時(shí)對象導航圖功能的強大的表達式語(yǔ)言。 它的語(yǔ)法類(lèi)似于傳統EL,但提供額外的功能,最出色的就是函數調用和簡(jiǎn)單字符串的模板函數。SpEL類(lèi)似于Struts2x中使用的OGNL表達式語(yǔ)言, 能在運行時(shí)構建復雜表達式、存取對象圖屬性、對象方法調用等等,并且能與Spring功能完美整合,如能用來(lái)配置Bean定義。

  SpEL主要提供基本表達式、類(lèi)相關(guān)表達式及集合相關(guān)表達式等,詳細參見(jiàn)Spring 表達式語(yǔ)言 (SpEL) 。

  類(lèi)似與OGNL,SpEL具有expression(表達式),Parser(解析器),EvaluationContext(上下文)等基本概念;類(lèi)似與MVEL,SpEl也提供了解釋模式和編譯模式兩種運行模式。

  //解釋器模式Foo foo = new Foo();foo.setName("test");// Turn on:// - auto null reference initialization// - auto collection growingSpelParserConfiguration config = new SpelParserConfiguration(true,true);ExpressionParser parser = new SpelExpressionParser(config);String expressionStr = "#foo.name == 'test'";StandardEvaluationContext context = new StandardEvaluationContext();context.setVariable("foo",foo);Expression expression = parser.parseExpression(expressionStr);Boolean result = expression.getValue(context,Boolean.class);//編譯模式config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, RunSpel.class.getClassLoader());parser = new SpelExpressionParser(config);context = new StandardEvaluationContext();context.setVariable("foo",foo);expression = parser.parseExpression(expressionStr);result = expression.getValue(context,Boolean.class);

  Groovy

  Groovy除了Gradle 上的廣泛應用之外,另一個(gè)大范圍的使用應該就是結合Java使用動(dòng)態(tài)代碼了。Groovy的語(yǔ)法與Java非常相似,以至于多數的Java代碼也是正確的Groovy代碼。Groovy代碼動(dòng)態(tài)的被編譯器轉換成Java字節碼。由于其運行在JVM上的特性,Groovy可以使用其他Java語(yǔ)言編寫(xiě)的庫。

  Groovy可以看作給Java靜態(tài)世界補充動(dòng)態(tài)能力的語(yǔ)言,同時(shí)Groovy已經(jīng)實(shí)現了java不具備的語(yǔ)言特性:

  函數字面值;

  對集合的一等支持;

  對正則表達式的一等支持;

  對xml的一等支持;

  Groovy作為基于JVM的語(yǔ)言,與表達式語(yǔ)言存在語(yǔ)言級的不同,因此在語(yǔ)法上比表達還是語(yǔ)言更靈活。Java在調用Groovy時(shí),都需要將Groovy代碼編譯成Class文件。

  Groovy 可以采用GroovyClassLoader、GroovyShell、GroovyScriptEngine和JSR223 等方式與Java語(yǔ)言集成。

  GroovyClassLoader

  GroovyClassLoader是一個(gè)定制的類(lèi)裝載器,負責解釋加載Java類(lèi)中用到的Groovy類(lèi),也可以編譯,Java代碼可通過(guò)其動(dòng)態(tài)加載Groovy腳本并執行。

  class FooCompare{

  boolean compare(String toCompare){

  Foo foo = new Foo();

  foo.name = "test";

  return foo.name == toCompare;

  }}

  GroovyClassLoader loader = new GroovyClassLoader();Class groovyClass = null;try {

  String path = "FooCompare.groovy";

  groovyClass = loader.parseClass(new File(path));} catch (IOException e) {

  e.printStackTrace();}GroovyObject groovyObject = null;try {

  groovyObject = (GroovyObject) groovyClass.newInstance();} catch (InstantiationException e) {

  e.printStackTrace();} catch (IllegalAccessException e) {

  e.printStackTrace();}result = groovyObject.invokeMethod("compare", "test");assert result.equals(Boolean.TRUE);System.out.print(result);

  GroovyShell

  GroovyShell允許在Java類(lèi)中(甚至Groovy類(lèi))求任意Groovy表達式的值?梢允褂肂inding對象輸入參數給表達式,并最終通過(guò)GroovyShell返回Groovy表達式的計算結果。

  Foo foo = new Foo();foo.setName("test");Binding binding = new Binding();binding.setVariable("foo",foo);GroovyShell shell = new GroovyShell(binding);String expression = "foo.name=='test'";Object result = shell.evaluate(expression);assert result.equals(Boolean.TRUE);

  GroovyScriptEngine

  GroovyShell多用于推求對立的腳本或表達式,如果換成相互關(guān)聯(lián)的多個(gè)腳本,使用GroovyScriptEngine會(huì )更好些。 GroovyScriptEngine從您指定的位置(文件系統,URL,數據庫,等等)加載Groovy腳本,并且隨著(zhù)腳本變化而重新加載它們。如同 GroovyShell一樣,GroovyScriptEngine也允許您傳入參數值,并能返回腳本的值。

  FooScript.groovy

  package blog.brucefeng.info.groovy

  foo.name=="test";

  Foo foo = new Foo();foo.setName("test");Binding binding = new Binding();binding.setVariable("foo",foo);String[] paths = {"/demopath/"}GroovyScriptEngine gse = new GroovyScriptEngine(paths);try {

  result = gse.run("FooScript.groovy", binding);} catch (ResourceException e) {

  e.printStackTrace();} catch (ScriptException e) {

  e.printStackTrace();}assert result.equals(Boolean.TRUE);

  JSR223

  JSR223 是Java 6提供的一種從Java內部執行腳本編寫(xiě)語(yǔ)言的方便、標準的方式,并提供從腳本內部訪(fǎng)問(wèn)Java 資源和類(lèi)的功能,可以使用其運行多種腳本語(yǔ)言如JavaScript和Groovy等。

  Foo foo = new Foo();foo.setName("test");ScriptEngineManager factory = new ScriptEngineManager();ScriptEngine engine1 = factory.getEngineByName("groovy");engine1.put("foo",foo);try {

  result = engine1.eval(expression);} catch (javax.script.ScriptException e) {

  e.printStackTrace();}assert result.equals(Boolean.TRUE);

  使用中經(jīng)常出現的問(wèn)題

  因此Java每次調用Groovy代碼都會(huì )將Groovy編譯成Class文件,因此在調用過(guò)程中會(huì )出現JVM級別的問(wèn)題。如使用 GroovyShell的parse方法導致perm區爆滿(mǎn)的問(wèn)題,使用GroovyClassLoader加載機制導致頻繁gc問(wèn)題和 CodeCache用滿(mǎn),導致JIT禁用問(wèn)題等,相關(guān)問(wèn)題可以參考Groovy與Java集成常見(jiàn)的坑 。

  性能對比

  在這里簡(jiǎn)單對上面介紹到的OGNL、MVEL、SpEL和Groovy2.4 的性能進(jìn)行大致的性能測試(簡(jiǎn)單測試):

實(shí)現方式 耗時(shí)(MS)
Java 13
OGNL 2958
MVEL 225
SpEL 1023
Groovy 99

  通過(guò)這個(gè)簡(jiǎn)單測試發(fā)現,Groovy 2.4的性能已經(jīng)足夠的好,而MVEL的性能依然保持強勁,不過(guò)已經(jīng)遠遠落后與Groovy,在對性能有一定要求的場(chǎng)景下已經(jīng)不建議使用OGNL和SpEL。

  不過(guò)動(dòng)態(tài)代碼的執行效率還是遠低于Java,因此在高性能的場(chǎng)景下慎用。

  以下是測試代碼:

  package blog.brucefeng.info.performanceclass GroovyCal{

  Integer cal(int x,int y,int z){

  return x + y*2 - z;

  }}

  package blog.brucefeng.info.performance;public class RunPerform {

  public static void main(String[] args) {

  try {

  int xmax = 100,ymax = 100,zmax= 10;

  runJava(xmax, ymax, zmax);

  runOgnl(xmax, ymax, zmax);

  runMvel(xmax, ymax, zmax);

  runSpel(xmax, ymax, zmax);

  runGroovyClass(xmax, ymax, zmax);

  } catch (Exception e) {

  e.printStackTrace();

  }

  }

  public static void runJava(int xmax, int ymax, int zmax) {

  Date start = new Date();

  Integer result = 0;

  for (int xval = 0; xval < xmax; xval++) {

  for (int yval = 0; yval < ymax; yval++) {

  for (int zval = 0; zval <= zmax; zval++) {

  result += xval + yval * 2 - zval;

  }

  }

  }

  Date end = new Date();

  System.out.println("time is : " + (end.getTime() - start.getTime()) + ",result is " + result);

  }

  public static void runOgnl(int xmax, int ymax, int zmax) throws OgnlException {

  String expression = "x + y*2 - z";

  Map context = new HashMap();

  Integer result = 0;

  Date start = new Date();

  for (int xval = 0; xval < xmax; xval++) {

  for (int yval = 0; yval < ymax; yval++) {

  for (int zval = 0; zval <= zmax; zval++) {

  context.put("x", xval);

  context.put("y", yval);

  context.put("z", zval);

  Integer cal = (Integer) Ognl.getValue(expression, context);

  result += cal;

  }

  }

  }

  Date end = new Date();

  System.out.println("Ognl:time is : " + (end.getTime() - start.getTime()) + ",result is " + result);

  }

  public static void runMvel(int xmax, int ymax, int zmax) {

  Map context = new HashMap();

  String expression = "x + y*2 - z";

  Serializable compileExpression = MVEL.compileExpression(expression);

  Integer result = 0;

  Date start = new Date();

  for (int xval = 0; xval < xmax; xval++) {

  for (int yval = 0; yval < ymax; yval++) {

  for (int zval = 0; zval <= zmax; zval++) {

  context.put("x", xval);

  context.put("y", yval);

  context.put("z", zval);

  VariableResolverFactory functionFactory = new MapVariableResolverFactory(context);

  Integer cal = (Integer) MVEL.executeExpression(compileExpression, context, functionFactory);

  result += cal;

  }

  }

  }

  Date end = new Date();

  System.out.println("MVEL:time is : " + (end.getTime() - start.getTime()) + ",result is " + result);

  }

  public static void runSpel(int xmax, int ymax, int zmax) {

  SpelParserConfiguration config;

  ExpressionParser parser;

  config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, RunSpel.class.getClassLoader());

  parser = new SpelExpressionParser(config);

  StandardEvaluationContext context = new StandardEvaluationContext();

  Integer result = 0;

  String expressionStr = "#x + #y*2 - #z";

  Date start = new Date();

  for (Integer xval = 0; xval < xmax; xval++) {

  for (Integer yval = 0; yval < ymax; yval++) {

  for (Integer zval = 0; zval <= zmax; zval++) {

  context.setVariable("x", xval);

  context.setVariable("y", yval);

  context.setVariable("z", zval);

  Expression expression = parser.parseExpression(expressionStr);

  Integer cal = expression.getValue(context, Integer.class);

  result += cal;

  }

  }

  }

  Date end = new Date();

  System.out.println("SpEL:time is : " + (end.getTime() - start.getTime()) + ",result is " + result);

  }

  public static void runGroovyClass(int xmax, int ymax, int zmax) {

  GroovyClassLoader loader = new GroovyClassLoader();

  Class groovyClass = null;

  try {

  groovyClass = loader.parseClass(new File(

  "GroovyCal.groovy"));

  } catch (IOException e) {

  e.printStackTrace();

  }

  GroovyObject groovyObject = null;

  try {

  groovyObject = (GroovyObject) groovyClass.newInstance();

  } catch (InstantiationException e) {

  e.printStackTrace();

  } catch (IllegalAccessException e) {

  e.printStackTrace();

  }

  Integer result = 0;

  Date start = new Date();

  for (int xval = 0; xval < xmax; xval++) {

  for (int yval = 0; yval < ymax; yval++) {

  for (int zval = 0; zval <= zmax; zval++) {

  Object[] args = {xval,yval,zval};

  Integer cal = (Integer) groovyObject.invokeMethod("cal", args);

  result += cal;

  }

  }

  }

  Date end = new Date();

  System.out.println("Groovy Class:time is : " + (end.getTime() - start.getTime()) + ",result is " + result);

  }}

【Java中的動(dòng)態(tài)代碼編程】相關(guān)文章:

在Java中執行JavaScript代碼04-01

數控編程代碼大全03-09

數控編程M代碼大全04-24

Java基本編程技巧03-31

如何讓JAVA代碼更高效03-20

Java代碼的基本知識02-27

java證書(shū)的加密與解密代碼02-26

Java編程常見(jiàn)問(wèn)題匯總02-28

java非對稱(chēng)加密的源代碼(rsa)03-30

一级日韩免费大片,亚洲一区二区三区高清,性欧美乱妇高清come,久久婷婷国产麻豆91天堂,亚洲av无码a片在线观看