Spring的IOC本质就一个容器,也就是一个对象的工厂,我们通过配置文件注册我们的Bean对象,通过他进行对象的组装与床架。
SpEL表达式就是一种字符串编程,类似于JS里面的EVAL的作用,通过它可以运行字符串内容
特点:算是一种动态的编程在配置文件(xml配置文件或者注解表达式)--------------------------主流的编程都是基于GUI的开发模式(XML开发模式)里面的动态编程
重点:要是通过拼接字符串作为代码运行,SpEL就可以实现,一些灵活的功能
<bean id="numberGuess" class="org.spring.samples.NumberGuess"> <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/> <!-- other properties --> </bean> <bean id="taxCalculator" class="org.spring.samples.TaxCalculator"> <property name="defaultLocale" value="#{ systemProperties['user.region'] }"/> <!-- other properties --> </bean> <bean id="numberGuess" class="org.spring.samples.NumberGuess"> <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/> <!-- other properties --> </bean> <bean id="shapeGuess" class="org.spring.samples.ShapeGuess"> <property name="initialShapeSeed" value="#{numberGuess.randomNumber }"/> <!-- other properties --> </bean>
ExpressionParser parser = new SpelExpressionParser();
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
StandardEvaluationContext context = new StandardEvaluationContext(tesla);
String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class);
System.out.println(city); // Smiljan
tesla.setPlaceOfBirth(null);
city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class);
System.out.println(city); // null - does not throw NullPointerException!!!
否则:我们就只能通过JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 来编译字符串生成类
package com.test; import java.io.IOException; import java.lang.reflect.Method; import java.net.URI; import java.util.Arrays; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; public class CompileString { public static void main(String[] args) throws Exception { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); System.out.println(""+ToolProvider.getSystemJavaCompiler()); StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null); StringObject so = new StringObject( "CalculatorTest", "class CalculatorTest {" + " public int multiply(int multiplicand, int multiplier) {" + " System.out.println(multiplicand);" + " System.out.println(multiplier);" + " return multiplicand * multiplier;" + " }" + "}"); JavaFileObject file = so; Iterable files = Arrays.asList(file); JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, files); Boolean result = task.call(); System.out.println(result); if (result) { Class clazz = Class.forName("CalculatorTest"); Object instance = clazz.newInstance(); Method m = clazz.getMethod("multiply", new Class[] { int.class, int.class }); Object[] o = new Object[] { 3, 2 }; System.out.println(m.invoke(instance, o)); } } } class StringObject extends SimpleJavaFileObject { private String contents = null; public StringObject(String className, String contents) throws Exception { super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); this.contents = contents; } public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return contents; } }
这种模式要使用java自定义的类加载器进行加载对应的类,对于类加载器可以参考网上的其他的文章....,通过这样可以实现动态的编程。
本质上,不管是java还是JS代码以及注解,最好的方式就是支持基于字符串的动态编程实现,目前都可以实现...............................