java 反射 模仿spring IOC机制

29 篇文章 1 订阅
16 篇文章 0 订阅

IOC:即“控制反转”,不是什么技术,而是一种思想。使用IOC意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

本篇文章主要讲解一下IOC底层实现的原理(反射),Bean容器的实现,就不对IOC的概念进行详述了。

在Spring的配置文件中,经常看到如下配置:

<bean id="courseDao" class="com.qcjy.learning.Dao.impl.CourseDaoImpl"></bean>

那么通过这样配置,Spring是怎么帮我们实例化对象,并且放到容器中去了了?对,就是通过反射!!!
下面是Spring通过配置进行实例化对象,并放到容器中的伪代码:

//解析<bean .../>元素的id属性得到该字符串值为“courseDao”
String idStr = "courseDao";
//解析<bean .../>元素的class属性得到该字符串值为“com.qcjy.learning.Dao.impl.CourseDaoImpl”
String classStr = "com.qcjy.learning.Dao.impl.CourseDaoImpl";
//利用反射知识,通过classStr获取Class类对象
Class<?> cls = Class.forName(classStr);
//实例化对象
Object obj = cls.newInstance();
//container表示Spring容器
container.put(idStr, obj);


通过解析xml文件,获取到id属性和class属性里面的内容,利用反射原理获取到配置里面类的实例对象,存入到Spring的bean容器中。


当一个类里面需要应用另一类的对象时,Spring的配置如下所示:

<bean id="courseService" class="com.qcjy.learning.service.impl.CourseServiceImpl">
     <!-- 控制调用setCourseDao()方法,将容器中的courseDao bean作为传入参数 -->
     <property name="courseDao" ref="courseDao"></property>
</bean>

我们继续用伪代码的形式来模拟实现一下Spring底层处理原理:

//解析<property .../>元素的name属性得到该字符串值为“courseDao”
String nameStr = "courseDao";
//解析<property .../>元素的ref属性得到该字符串值为“courseDao”
String refStr = "courseDao";
//生成将要调用setter方法名
String setterName = "set" + nameStr.substring(0, 1).toUpperCase()
		+ nameStr.substring(1);
//获取spring容器中名为refStr的Bean,该Bean将会作为传入参数
Object paramBean = container.get(refStr);
//获取setter方法的Method类,此处的cls是刚才反射代码得到的Class对象
Method setter = cls.getMethod(setterName, paramBean.getClass());
//调用invoke()方法,此处的obj是刚才反射代码得到的Object对象
setter.invoke(obj, paramBean);


通过上面对Spring底层原理的分析,可以发现,其实并不难,用到的都是反射机制,通过反射实例化对象,存入到Spring的bean容器中。

下面是我自己的例子:

xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<bean id="u" class="com.hwj.test.User">
	 <property name="userName" value="test00" />
	</bean>
	<bean id="userService" class="com.hwj.test.UserService">
		<property name="user" bean="u" />
	</bean>
</beans>

ClassPathXmlApplicationContext.java

package com.hwj.test;

import java.io.File;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.PrimitiveIterator.OfDouble;

import javax.sound.midi.Soundbank;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;

public class ClassPathXmlApplicationContext implements BeanFactory {
	//模仿spring ioc容器
	Map<String, Object> beans = new HashMap<String, Object>();

	public ClassPathXmlApplicationContext() throws Exception {
		// 创建saxReader对象
		SAXReader reader = new SAXReader();
		// 通过read方法读取一个文件 转换成Document对象
		Document document = reader.read(new File("E:/workspace/eworkspace/demoTruck/src/main/resources/dom.xml"));
		// 获取根节点元素对象
		Element node = document.getRootElement();
		System.out.println("当前节点的名称::" + node.getName());
		// beans下的节点
		List<Element> list = node.elements();
		for (Element bean : list) {
			String id = bean.attributeValue("id");
			String className = bean.attributeValue("class");
			Object o = Class.forName(className).newInstance();
			//将对象放入容器中
			beans.put(id, o);
			Iterator<Element> it = bean.elementIterator();
			//遍历bean下面的子节点
			while (it.hasNext()) {
				Element propertyElement = it.next();
				String propertyName = propertyElement.attributeValue("name");
				String propertyValue = propertyElement.attributeValue("bean");
				String value = propertyElement.attributeValue("value");
				Object beanObject=null;
				if(propertyValue!=null) {
					//获取从map中获取需要注入的对象
					beanObject = beans.get(propertyValue);
				}
				String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
				Method method = null;
				//如果是注入普通的属性值
				if (value != null) {
					method = o.getClass().getMethod(methodName, String.class);
					method.invoke(o, value);
				}
				//注入对象
				else {
					method = o.getClass().getMethod(methodName, User.class);
					method.invoke(o, beanObject);
				}
			}
		}
	}

	@Override
	public Object getBean(String name) throws BeansException {
		// TODO Auto-generated method stub
		return beans.get(name);
	}

	@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean containsBean(String name) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String[] getAliases(String name) {
		// TODO Auto-generated method stub
		return null;
	}

}

测试:

package com.hwj.test;

import java.io.File;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.xmlbeans.soap.SOAPArrayType;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.BeanFactory;

public class DomTest {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		BeanFactory beanFactory=new ClassPathXmlApplicationContext();
        UserService userService=(UserService) beanFactory.getBean("userService");
        System.out.println("userservice user的值:"+userService.getUser().getUserName());
       
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值