模拟spring注入

尊重原创:原创和源代码地址

项目中的的spring出现问题,不想使用spring框架进行注入,编写一个简单的spring,实现xml解析和类的注入。所有的框架都可以用java项目,用到了java提供的基础类,所以用到的原理也就呢么多(我刚开始工作2个月,说的不对请谅解)。因此spring用到了注入用到java中的反射机制,aop用到了java的代理机制proxy对象。总结一下自己的设计:

设计范围三层:

第一层是实体层,根据自己定义的xml规则抽象除了两个对象实体,一个是实体对象bean(程序中定义为BeanDefineModel),另一个是属性实体对象(程序中定义为ParamDefineModel)。

第二层是xml解析层,既将xml进行解析,生成beanDefineFactory对象的连。(这里采用的第三方的dom4j的jar包)进行解析,将xml解析成一个一个的对象链。

第三层是实例化,并对实例化的对象进行属性注入。ApplicationContext

(本模拟spring用到了dom4j.jar还有commom.collection.jar和common.lang.jar)源码在后面资源中提供。所有的框架开始是定义xml规范,对规范的内容进行解析注入,最终生成一个访问bean的hashMap的接口,xml格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<[email protected] chunlei 原创:url-->
<beans>
    <bean name="blueHair" class ="com.test.source.Hair">
    	<property name="color" value="blue"></property>
    	<property name="hair" value="good"></property>
    	<property name="stringList">
    		<list>
    			<li value="zhang"></li>
    			<li value="chun"></li>
    		</list>
    	</property>
    </bean>
   <bean name ="body" class ="com.source.Body">
		<property name="name" value="zhang"></property>
		<property name="hair" ref="blueHair"></property>
    </bean>
</beans>  

作为bean标签只有name 和class当然后期你可以加上type等属性,不过需要对model解析进行修改,property的属性定义为name,value,ref,list,map,和set。map和set的没有实现,其他的都实现了,会抽时间继续填补自己的框架。其中list标签必须以li来开头,这样li下面可以存在name,value,ref,list等属性,实现param的model的重用。同样在解析和实例化的时候可以使用递归。

在完成这个任务时遇到问题就是在注入的地方,因为利用反射机制寻找到方法可以使用method(methodName,propertyType)来获得方法,不过容易报错,因为我们在xml中注入的时候有可能使用实体类注入,有可能使用接口注入。后来使用了比较麻烦的办法,先拼接方法名,然后获得bean的所有方法,遍历所有的方法根据方法名找到方法,然后找到方法的参数类型,判断是否和注入属性是否相同,若相同则直接调用反射机制进行注入,若不同则得到参数的所有接口,遍历接口判断是否和参数接口相同来进行注入,具体的代码如下:,最终代码在公司,没有拿来,现在的代码是自己回来加班做的,只考虑到实体类注入,下发上去,后期会修改。资源在后面分享,中秋节的时间排满了,还要看solr的源代码等,作业很多。谅解。重要代码,递归注入:

<pre name="code" class="java">package com.test;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

public class ApplicationContext{

	private static HashMap<String,Object> hashMap = new HashMap<String,Object>();//用来存放bean对象

	public static HashMap<String,Object> getBeanMap(String xmlPath){
		List<BeanDefine> beanDefineList = BeanDefineFactory.getBeanDefineList(xmlPath);//获得beanDefineList的
		if(CollectionUtils.isNotEmpty(beanDefineList)){
			for(BeanDefine beanDefine : beanDefineList){//遍历beanDefineList获得所有的beanDefine
				if(beanDefine != null){
					String beanName = beanDefine.getBeanName();//以beanName作为key放到beanMap中
					Object object = getBeanObject(beanDefine);//将beanDefine转化为bean对象
					hashMap.put(beanName, object);
				}
			}
		}
		return hashMap;
	}

	public static Object getBeanObject(BeanDefine beanDefine){
		String beanClass = beanDefine.getBeanClass();//获得bean的类型
		Object beanObject = getObjectByClass(beanClass);//根据bean对象获得对象
		List<ParamDefine> paramDefineList = beanDefine.getPropertyList();//bean获取propertyList
		if(CollectionUtils.isNotEmpty(paramDefineList)){
			for(ParamDefine paramDefine : paramDefineList){//遍历属性列表进行注入
				if(paramDefine != null){
					String paramName = paramDefine.getPropertyName();
					Object paramObject = getParamObject(paramDefine);//获得paramDefine对象
					beanObject = getRegistBeanObject(beanObject,paramName,paramObject);//注入bean对象
				}
			}
		}
		return beanObject;
	}

	public static Object getParamObject(ParamDefine paramDefine){
		Object paramObject = null;
		String paramValue = paramDefine.getPropertyValue();//注入的是String类型
		if(StringUtils.isNotEmpty(paramValue)){
			paramObject = new String(paramValue);
			return paramObject;
		}
		String propertyRef = paramDefine.getPropertyRef();//判断注入是否Ref类型
		if(StringUtils.isNotEmpty(propertyRef)){
			if(hashMap.containsKey(propertyRef)){
				paramObject = hashMap.get(propertyRef);
			}
			return paramObject;
		}
		List<ParamDefine> paramDefineList = paramDefine.getList();//判断注入是否List类型
		if(CollectionUtils.isNotEmpty(paramDefineList)){
			List<Object> list = new LinkedList<Object>();
			for(ParamDefine tempParamDefine : paramDefineList){
				Object tempParamObject = getParamObject(tempParamDefine);
				list.add(tempParamObject);
			}
			return paramObject = list;
		}
//		Set<ParamDefine> paramDefineSet = paramDefine.getSet();//判断注入是否Set类型
//		if(CollectionUtils.isNotEmpty(paramDefineList)){
//			object = registObjectBySet(object,paramName,paramDefineList);
//			return object;
//		}
//		Map<String,ParamDefine> paramDefineMap = paramDefine.getMap();//判断是否是Map类型
//		if(paramDefineMap != null && paramDefineMap.size() !=0){
//			object = registObjectByMap(object,paramName,paramDefineMap);
//			return object;
//		}
		return paramObject;
	}

	/**
	 * 使用java反射机制对bean对象进行注入
	 * @param beanObject bean对象
	 * @param paramName 属性名称
	 * @param paramObject 属性参数
	 * @return
	 */
	public static Object getRegistBeanObject(Object beanObject,String paramName,Object paramObject){
		 String methodName = "set" + paramName.substring(0,1).toUpperCase()+paramName.substring(1);//获取方法的名称
		 System.out.println(paramObject.getClass().toString());
		 System.out.println(methodName);
		 try {
			Method method = beanObject.getClass().getMethod(methodName, paramObject.getClass());//通过class类型,方法名和参数类型来获得方法
			method.invoke(beanObject,paramObject);//java反射调用set方法,进行属性设置
			 } catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 return beanObject;
	}

	/**
	 * 根据xml中bean的class属性值来创建bean对象:这里的bean对象时未被设置属性的对象
	 * @param classNamee
	 * @return
	 */
	public static Object getObjectByClass(String beanClass){//根据ClassName生成对象
		Object beanObject = null;
		try {
			beanObject = Class.forName(beanClass).newInstance();//调用class驱动实例化对象
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return beanObject;
	}
}

其中额注入代码有缺陷,等后期整理的更好后在弄,同时让set和map都可以,大体的结构已经设计好了。

				
时间: 2024-10-14 01:56:24

模拟spring注入的相关文章

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

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

Java反射—模拟Spring的Aop

1.    大概流程 上篇文章已经结合Java反射解释了SpringAop的原理,这里我们简单模拟以下Spring的Aop实现.大体流程如下: ?  创建一个properties配置文件模拟Spring配置文件. ?  创建一个增强接口与一个实现类模拟Spring的Advice. ?  创建一个生成代理的工厂类,并在InvocationHandler类的invoke方法中织入增强方法(即aop). ?  创建一个生成Bean的工厂类(类似IOC工厂,只创建bean,没有依赖注入的功能),生成Be

容器学习(一):动手模拟spring的IoC

介绍 学习经典框架的实现原理以及设计模式在事实上际中的运用,是很有必要的,能够让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能.明确原理后,能够更好的使用它,进而为进行面向对象提供一种思路. 点击下载源代码:下载 动手模拟IoC实现 首先我们把我们用的dao.service.entity定义出来: Student.java : package com.bzu.entity; public class Student { private int id; private Strin

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

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

Java 模拟Spring

一.概述 1.目标:模拟Spring的Ioc 2.用到的知识点:利用jdom的xpath读取xml文件,反射 二.有如下文件: 1.applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans> <bean id="vehicle" class="com.tong.spring.factory.Car"> </

SSH框架系列:Spring读取配置文件以及获取Spring注入的Bean

分类: [java]2013-12-09 16:29 1020人阅读 评论(0) 收藏 举报 1.简介 在SSH框架下,假设我们将配置文件放在项目的src/datasource.properties路径下,Spring的配置文件也是src/applicationContext.xml路径下,那么我们可以借助Spring的property-placeholder读取配置文件,然后注入Bean中.我们在程序中,可以根据Bean的Id,获取注入的值.这样我们就可以借助Spring来读取配置文件. 2.

JSP 获取Spring 注入对象

<%@ page import="org.springframework.web.context.support.WebApplicationContextUtils"%> <%@ page import="org.springframework.context.ApplicationContext"%> ServletContext sc = this.getServletConfig().getServletContext(); Appl

Spring注入aspectJ切面

1.用关键字aspect即可声明一个切面如:                    切面定义完毕,可以发现,pointcut被当做一个类型,指定切点还是用execution表达式:after()和returning()也被当做一个类型来声明一个通知 2.在JudgeAspect中有一个CriticismEngine类型的成员变量,为了实现对象间的松耦合,我们在aspectJ中使用Spring的依赖注入来为JudgeAspect注入CriticismEngine对象.首先将CriticismEng

spring注入与代理对象两个对象

[INFO ] 2015-05-18 15:44:37:124 [com.yjm.dao.CommonDAO] - CommonDAO...初始化... [INFO ] 2015-05-18 15:44:37:137 [com.yjm.service.FoodService] - FoodService...初始化...18794463 [email protected] [INFO ] 2015-05-18 15:44:37:336 [com.yjm.service.FoodService]