zoukankan      html  css  js  c++  java
  • 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换

       作者: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

    因为今天老师给我安排了任务,我将在未来有时间的情况下。将博客翻译成中文并解析。


  • 相关阅读:
    oc结构
    iOS分类
    iOS协议
    缓存无底洞现象
    数据库备份,恢复
    PHP邮件发送库:Swiftmailer
    PHP分页组件:Paginator
    PHP验证码类
    PHP日期和时间处理组件-Carbon
    composer的一些操作
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5257687.html
Copyright © 2011-2022 走看看