反射结合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的信息

 

时间: 2024-11-08 20:23:58

反射结合xml简单的模拟spring创建bean的相关文章

spring创建Bean对象的控制

1.spring创建Bean对象的控制 a.控制对象创建方式(使用范围),在<bean>元素中使用scope属性控制,scope可以支持singleton或prototype,默认值是singleton <bean scope= "singleton"> 该组件在spring容器里只有一个bean对象.每次取出的bean都是同一个bean,相当于单例模式 <bean scope = "prototype">该组件每次使用getBe

Spring创建Bean的顺序

一直对Spring创建bean的顺序很好奇,现在总算有时间写个代码测试一下.不想看过程的小伙伴可以直接看结论 目录结构: 其中:bean4.bean5包下的class没有注解@Component,测试过程中,这两个包的class会直接通过<bean class="XXXXX"/>的方式创建.bean1.bean2.bean3包下的class注解了@Component,以便component-scan扫描.另外,bean创建之间没有依赖关系,例如bean1的创建不依赖于其他b

Spring 创建Bean的6种方式

前言 本文讲解了在Spring 应用中创建Bean的多种方式,包括自动创建,以及手动创建注入方式,实际开发中可以根据业务场景选择合适的方案. 方式1: 使用Spring XML方式配置,该方式用于在纯Spring 应用中,适用于简单的小应用,当应用变得复杂,将会导致Bean管理很麻烦 <bean id="xxxx" class="xxxx.xxxx"/> 方式2: 使用@Component,@Service,@Controler,@Repository注

spring创建bean的三种方式

1.使用构造器创建bean 1.1.使用无参构造器创建 package com.ly.spring; public class Person { private String name; public void say(String name) { System.out.println("你好,我叫"+name); } } <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&

使用JDom解析XML文档模拟Spring的配置文件解析

在J2EE项目中可能会涉及到一些框架的使用,最近接触到了SSH,拿Spring来说配置文件的使用是相当重要的,Spring的配置文件是一个xml文件,Spring是如何读取到配置文件并进行依赖注入的呢?今天先来说说xml文件的解析. 解析xml文件可以使用jdom,下面我以一个小栗子来说说xml文件的解析. 1.首先下载jdom,在这里我以jdom2.0.6为例 2.接下来附上一个xml文档 <?xml version="1.0" encoding="UTF-8&quo

Spring 创建bean的时机

默认在启动spring容器的时候,spring容器配置文件中的类就已经创建完成对象了        在<bean>中添加属性lazy-init,默认值为false.    true  在context.getBean的时候才要创建对象                      *  优点                                    如果该bean中有大数据存在,则什么时候context.getBean,什么时候创建对象                         

Java反射机制详解(3) -java的反射和代理实现IOC模式 模拟spring

IOC(Inverse of Control) 可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”.在Spring中,通过IOC可以将实现类.参数信息等配置在其对应的配置文件中,那么当 需要更改实现类或参数信息时,只需要修改配置文件即可,这种方法在上例的基础上更进一步的降低了类与类之间的耦合.我们还可以对某对象所需要的其它对象进 行注入,这种注入都是在配置文件中做的,Spring的IOC的实现原理利用的就是Java的反射机制, Spring还充当了工厂的角色,我们不需要自己建立工厂类.S

采用dom4j和反射模拟Spring框架的依赖注入功能

Spring的依赖注入是指将对象的创建权交给Spring框架,将对象所依赖的属性注入进来的行为.在学习了dom4j后,其实也可以利用dom4j和反射做一个小Demo模拟Spring框架的这种功能.下面是具体的步骤: 第一步,编写配置文件.配置文件的书写,采用了和Spring的配置文件applicationContext.xml一样的书写规则: <?xml version="1.0" encoding="UTF-8"?> <!-- applicati

反射-Spring管理Bean,注入Bean属性的反射机制。

#反射 1.是JAVA API,是Java提供的现成的类!! --接受API提供的功能! 2. 是Java提供的动态执行机制,动态加载类,动态创建对象,动态访问属性,动态调用方法. ##反射用途 1. eclipse 中解析类的结构使用了反射 2.JUnit识别被测试方法使用了反射 -- JUnit3 利用了反射查找test开头的方法 -- JUnit4 利用了反射解析@Test查找测试方法 3.Spring 管理Bean对象,注入Bean属性使用了反射 --利用反射创建Bean对象实例 --利