反射结合xml简单的模拟spring创建bean

Posted bluedarkni

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反射结合xml简单的模拟spring创建bean相关的知识,希望对你有一定的参考价值。

框架最底层其实就是通过反射实现的,就像spring,当你配置各种各样的bean时都是以配置文件的形式配置的,你需要用到哪些bean就配哪些,spring容器就会根据你的需求去动态加载,这儿写一个简单的例子模拟一下:

1.加深对反射的理解,

2.了解一下框架的实现的原理

3.通过dom4j对xml的解析

 

两个简单的类:

User:

public class User {
	
	private String userName;
	private  String userPwd;
	private String userAge;
	
	public String getUserAge() {
		return userAge;
	}

	public void setUserAge(String userAge) {
		this.userAge = userAge;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}
	
	public String getUserPwd() {
		return userPwd;
	}

	public void setUserPwd(String userPwd) {
		this.userPwd = userPwd;
	}
}

  Student类:

public class Student {
	
	private String stuName;
	private String stuNo;
	
	public String getStuName() {
		return stuName;
	}
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	public String getStuNo() {
		return stuNo;
	}
	public void setStuNo(String stuNo) {
		this.stuNo = stuNo;
	}

}

  配置xml文件:<bean-class>里面是类的包名+类名

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <bean>
        <bean-name>user</bean-name>
        <bean-class>com.bwf.test.User</bean-class>
        <init>
            <property name="userName">zhangsan</property>
            <property name="userAge">18</property>
            <property name="userPwd">123456</property>
        </init>
    </bean>
    
    <bean>
        <bean-name>user1</bean-name>
        <bean-class>com.bwf.test.User</bean-class>
        <init>
            <property name="userName">lisi</property>
            <property name="userPwd">654321</property>
            <property name="userAge">24</property>
        </init>
    </bean>
    
    <bean>
        <bean-name>student</bean-name>
        <bean-class>com.bwf.test.Student</bean-class>
        <init>
            <property name="stuName">wangwu</property>
            <property name="stuNo">1</property>
        </init>
    </bean>    
</beans>

解析xml为对象赋值及测试:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.bwf.test.Student;
import com.bwf.test.User;

public class XMLRefelct {

	public static void main(String[] args) {
		try {
			readXML();
		} catch (Exception e) {			
			e.printStackTrace();
		}
	}
	/**
	 * 读xml 文件
	 * @throws Exception
	 */
	public static void readXML() throws Exception{		
		InputStream in = null;
		try {
			in = new FileInputStream(new File("src/spring.xml"));
		} catch (FileNotFoundException e) {			
			e.printStackTrace();
		}		
		SAXReader reader = new SAXReader();		
		try {
			Document document = reader.read(in);   //读xml
			Element root = document.getRootElement();			
			List<Element> beans = root.elements();	//获取xml中的所有<bean>		
			for(Element bean : beans){
				bean.element("bean-class").getStringValue(); //获取配置的类的全路径名  
										//   <bean-class>com.bwf.test.User</bean-class>
				//System.out.println(bean.element("bean-class").getStringValue());
				//通过全路径名 反射得到Class 对象
				Class<?> c = Class.forName(bean.element("bean-class").getStringValue()); 
				
				List<Element> properties = bean.element("init").elements("property");//获取配置里面的所有属性
				
				Object o = c.newInstance(); //反射创建对象
				
				for(Element property : properties){					
					//判断属性是否在类的属性中存在      并为对象初始化配置的值
					o = checkPropertyEsxit(property.attribute("name").getStringValue(),o,c,property.getStringValue());				
				}	
				
				test(o);	//调用测试方法	
			}			
		} catch (DocumentException e) {
			
			e.printStackTrace();
		}
	}
	/**
	 * 判断属性是否在类的属性中存在      并为对象初始化配置的值
	 * @param propertyName
	 * @param o
	 * @param c
	 * @param propertyValue
	 * @return
	 */
	public static Object checkPropertyEsxit(String propertyName,Object o ,Class<?> c,String propertyValue ){
		
		Field[] fields = c.getDeclaredFields();
		
		boolean isExsit = false;//初始化为不存在
		
		for(Field field:fields){
			
			if(field.getName().equals(propertyName)){
				//说明属性存在
				isExsit = true;
				//拼接set方法的规范名字
				String setMethod = "set"+String.valueOf(field.getName().charAt(0)).toUpperCase()+
						field.getName().substring(1);
				try {
					//获取set方法
					Method m = c.getDeclaredMethod(setMethod, field.getType());
					
					try {
						//调用set方法初始化属性的值
						m.invoke(o, new Object[]{propertyValue});
						
					} catch (IllegalAccessException e) {						
						e.printStackTrace();
					} catch (IllegalArgumentException e) {						
						e.printStackTrace();
					} catch (InvocationTargetException e) {		
						e.printStackTrace();
					}										
				} catch (NoSuchMethodException e) {					
					e.printStackTrace();
				} catch (SecurityException e) {					
					e.printStackTrace();
				}				
			}
		}		
		if(isExsit){
//			System.out.println(propertyName+"存在");
			
		}else{
//			System.out.println(propertyName+"不存在");
			 try {
				throw new NoSuchFieldException(propertyName + "属性不存在" );
				
			} catch (NoSuchFieldException e) {				
				e.printStackTrace();
			}
		}		
		return o;
	}
	
	/**
	 * 测试对象是否已经初始化
	 * @param o
	 */
	public static  void test(Object o ){				
		if(o instanceof User){
			User user = (User)o;
			System.out.println(user.getUserName());
			System.out.println(user.getUserPwd());
			System.out.println(user.getUserAge());
			System.out.println("----------------");
		}else if(o instanceof Student){
			Student s = (Student)o;
			System.out.println(s.getStuNo());
		}
	}
}

  

结果:配置了两个user 一个 Student 输出了两个user的信息和student的信息

 

 

以上是关于反射结合xml简单的模拟spring创建bean的主要内容,如果未能解决你的问题,请参考以下文章

Java通过DOM解析假装实现Spring中Bean注入

Spring IOC的简单实现

这些简单的Spring Bean注入方式,你都会吗?

spring IOC容器中装配Bean(XML)

自己实现简单Spring Ioc

spring 配置bean 怎么使用