利用java反射机制 读取配置文件 实现动态类加载以及动态类型转换
来源:互联网 发布:自制编程语言pdf 编辑:程序博客网 时间:2024/05/21 09:17
作者:54dabang
在spring的学习过程之中,我们可以看出通过配置文件来动态管理bean对象的好处(松耦合 可以让零散部分组成一个整体,而这些整体并不在意之间彼此的细节,从而达到了真正的物理上的疏散耦合,而非逻辑,有了IOC之后,我们可以让SPRING充当各框架中的整合器,把技术框架进行完美的结合)。
Spring实现的一个重要的机制是通过反射(java.lang.reflect)读取配置文件,通过配置文件来动态生成配置文件中的类对象。Java动态加载类主要是为了不改变主程序代码,通过修改配置文件就可以操作不同的对象执行不同的功能。
由于java是强类型语言,本文根据一篇老外的博客,给出了一种可以实现动态类型转换的可行性方法和思路。
本文主要帮助你完成一下学习目标:
(1)反射机制最基础的学习。
(2) 通过最基础的java正则表达式读取配置文件,获取需要的信息。
(3) 模拟spring的IOC机制,实现类的动态加载。
(4) 给出程序源码,测试,总结
(5) 利用java反射机制来实现动态类型转换(待完成)
一 java反射机制最基础的学习
(1)关于java反射机制最基础的学习可以参考博客
http://blog.csdn.net/xiaoxian8023/article/details/9206055,内容比较详细。但是这篇文章里查找方法时,只能根据methodName进行查找,无法精确查找到重载的方法(根据参数查找)。
这里讲两种方式列出来:
A)只通过方法的名字进行查找 并调用 参数:被调用对象的实例 方法名 方法调用所需要的参数
public Object invokeMethodGernaral(Object owner,String methodName,Object[]args) { //a.先获取对象所属的类 Class ownerClass=owner.getClass(); Method method=null; Object result=null; //b.获取需要调用的方法 for(Method m:ownerClass.getDeclaredMethods()) { if(m.getName().equalsIgnoreCase(methodName)) { method=m; break; } } try { //c.调用该方法 result=method.invoke(owner, args);//调用方法 } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; }
B)只通过方法的名字和参数进行精确匹配查找 并调用 参数:被调用对象的实例 方法名 参数的类型 方法调用所需要的参数
<pre name="code" class="java">public Object invokeMethod(Object owner,String methodName,Class[]clz,Object[] args) throws Exception { //a.得到对象所属类 Class ownerClass=owner.getClass(); //b.根据方法名称和参数名称 获取该类的某个方法 Method method=ownerClass.getMethod(methodName,clz);//第二个参数是通过类型来获取 有个缺点就是参数类型必须要填写 //c.执行某个对象的方法 Object result=method.invoke(owner,args); //必须要有类对象才可以调用 //d.输出结果信息 System.out.println("结果返回值:"+ result); return result; }
二 通过最基础的java正则表达式读取配置文件,获取需要的信息。
从配置文件里读取信息,主要是用到IO流的操作,比较简单。为方便大家理解,我这里将其简化为一个字符串,然后利用正则表达式从中提取信息。
关于正则表达式的详细学习,可以参考我的博客:
http://blog.csdn.net/leixingbang1989/article/details/26486927
例如要匹配一下类型的字符串:
<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
其中标红的部分为想要获取的数据,注意这里要获取的数据长度不固定,并且可能为unicode
Gb2312等其他编码类型,在这里我们所希望获取的是其编码方式。
这里给出一段最简单的代码:
public static String parse (String s){ Pattern pattern =Pattern.compile("charset=(.+?)\""); //通配符中也要加入转移字符 (.+?)代表要查找的内容 Matcher matcher=pattern.matcher(s); while(matcher.find()) { System.out.println(matcher.group(1)); } return s;}
三 模拟spring的IOC机制,读取配置文件,实现类的动态加载
Spring的一个配置文件格式如下:
<beans><bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" ></bean><bean id="userService" class="com.bjsxt.service.UserService" ><property name="userDAO" bean="u"/></bean></beans>
我们可以用Pattern pattern =Pattern.compile("<beans>(.+?)</beans>");来获取bean对象配置信息,然后再次利用正则表达式获取每个bean信息。
在这里 我自定义了一个配置文件信息,放到字符串中。
其配置格式为: 属性名称:值,
String Configure="Class:com.bjsxt.service.school,Method:getStudentInfo,args:Tom,argsType:java.lang.String";//格式固定 可以用正则表达式提取String []split={":",","};//格式为 name:value, 所以分隔符为 : , parseData p=new parseData(Configure);//实现方式为正则表达式提取需要的字符串//(1) 获取类名 方法名 参数 参数类型信息 String className= p.getInfo("Class", split); String MethodName=p.getInfo("Method", split); String arg=p.getInfo("args", split); Object []args={arg};String argsType=p.getInfo("argsType", split);
四给出程序源码,测试,总结
package com.bjsxt.service;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class DynamicInvocation { public static void main(String[] a) throws Exception {String Configure="Class:com.bjsxt.service.school,Method:getStudentInfo,args:Tom,argsType:java.lang.String";//格式固定 可以用正则表达式提取String []split={":",","};//格式为 name:value, 所以分隔符为 : , parseData p=new parseData(Configure);//实现方式为正则表达式提取需要的字符串//(1) 获取类名 方法名 参数 参数类型信息 String className= p.getInfo("Class", split); String MethodName=p.getInfo("Method", split); String arg=p.getInfo("args", split); Object []args={arg}; String argsType=p.getInfo("argsType", split);//(2) 创建未知对象实例Object s=Class.forName(className).newInstance();// 注意我们目前创建的对象并不知道其类型//(3)方法调用//3.1仅通过方法名查找查找方法并调用 缺点:有可能有方法是重载的DynamicInvocation inv=new DynamicInvocation();inv.invokeMethodGernaral(s, MethodName, args);//3.2通过方法名 和参数 查找方法并调用Class cls=Class.forName(argsType);System.out.println(cls.getName());Class []clz={cls};inv.invokeMethod(s, MethodName, clz, args);//(4)动态强制类型转换Class intClass=Class.forName("java.lang.Integer");System.out.println(Integer.class);} public Object invokeMethodGernaral(Object owner,String methodName,Object[]args)//只通过方法的名字进行查找 并调用 { //a.先获取对象所属的类 Class ownerClass=owner.getClass(); Method method=null; Object result=null; //b.获取需要调用的方法 for(Method m:ownerClass.getDeclaredMethods()) { if(m.getName().equalsIgnoreCase(methodName)) { method=m; break; } } try { //c.调用该方法 result=method.invoke(owner, args);//调用方法 } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; } public Object invokeMethod(Object owner,String methodName,Class[]clz,Object[] args) throws Exception { //a.得到对象所属类 Class ownerClass=owner.getClass(); //b.根据方法名称和参数名称 获取该类的某个方法 Method method=ownerClass.getMethod(methodName,clz);//第二个参数是通过类型来获取 有个缺点就是参数类型必须要填写 //c.执行某个对象的方法 Object result=method.invoke(owner,args); //必须要有类对象才可以调用 //d.输出结果信息 System.out.println("结果返回值:"+ result); return result; } }
package com.bjsxt.service;import java.util.regex.Matcher;import java.util.regex.Pattern;public class parseData {private String strSource;//数据源public parseData(String s){this.strSource=s;}public String getInfo(String name,String []split)//名称,值,分隔符{String str=name+split[0]+"(.+?)"+split[1]; //System.out.println(str); Pattern pattern =Pattern.compile(str);//匹配的模式 Matcher matcher=pattern.matcher(this.strSource);String value="";boolean isFind=false;if(matcher.find()) {value=matcher.group(1); }else//可能是最后一个字符 { pattern=Pattern.compile(name+split[0]+"(.+?)"+"$");//$ 表示为限定结尾 matcher=pattern.matcher(this.strSource); if(matcher.find()) { value=matcher.group(1); } }return value;}}
五 利用java反射机制来实现动态类型转换(待完成)
主要实现思想来自于老外的一篇博客:
http://prajith-javatechnical.blogspot.in/2014/09/casting-java-object-dynamically-using.html
由于今天老师给我安排了任务,我将在未来有时间的情况下,将博客翻译成中文并解析。
- 利用java反射机制 读取配置文件 实现动态类加载以及动态类型转换
- 利用java反射机制 读取配置文件 实现动态类加载以及动态类型转换
- 利用反射实现类的动态加载
- 利用反射实现类的动态加载
- 利用反射实现类的动态加载
- 利用反射实现类的动态加载
- Java利用反射动态加载类实战
- 动态加载类(JAVA反射机制)
- Java反射机制-动态加载类
- 使用反射机制动态加载配置文件
- 利用反射加载配置文件中的类动态生成集合
- 利用java反射机制实现动态向下转型
- 利用java反射机制实现动态导出excel
- 利用反射动态加载Assembly动态执行类型方法
- JFig读取配置文件,实现动态加载
- 利用反射实现窗体动态加载
- 利用java反射机制动态创建对象
- Java反射机制之动态加载
- 发现一个很不错的正则表达式生成器
- Android Service与Activity之间通信的几种方式
- ORACLE错误(ora查询索引)
- ASP.NET中的WebService一个简单的例子
- PHP程序员的技术成长规划
- 利用java反射机制 读取配置文件 实现动态类加载以及动态类型转换
- VC中实现历史记录的全面清除
- DOS/DDOS攻击的iptables主动防御
- 前端整合CMS发布
- Android动态加载jar/dex
- 第8周项目2-加班费
- 第八周 项目三 函数多分段求值
- maven之继承、聚合、依赖
- 【WP开发】实现“摇一摇”功能