`
cowboy_bebop
  • 浏览: 111693 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

模拟spring @Resource方式的依赖注入.

 
阅读更多

 

 

package org.cgz.test;
 
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import org.apache.commons.beanutils.ConvertUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
 
public class MyClassPathXmlApplicationContext {
 
	private List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
	private Map<String, Object> intsances = new HashMap<String, Object>();
	/**
	* 容器初始化时 传入配置文件名称 读取配置文件..实例化bean
	* @param configFileName
	*/
	public MyClassPathXmlApplicationContext(String configFileName) {
		readConfig(configFileName);
		instanceBeans();
		annotationInject();
		Injected();
	}
&nbsp;
	/**
	* 注解实现依赖注入
	*/
	private void annotationInject() {
		/**
		* 遍历bean,获取bean里的所有属性描述对象,遍历属性描述对象数组.
		* ---获取属性的setter方法.如果该属性setter方法存在,判断方法上是否有MyResource注解,
		*     如果有,获取注解对象,通过注解对象获取name值
		*         如果name值存在:根据name值查找Map中是否有该名称的bean,如果有,调用该属性的setter方法执行注入.
		*         如果name值不存在:获取该属性的名称,从map中查找是否有此名称的bean.
		*                         如果有:调用setter方法注入
		*                         没有:获取该属性的类型,遍历map查找map中是否有和此属性类型一致的bean,如果有,则执行注入
		* 
		*---获取该属性,判断该属性上是否有MyResource注解
		*     如果有:获取该注解的对象,通过该对象获取name值
		*        如果name值存在:根据name值查找map中是否有该bean如果有则执行注入
		*        如果name值不存在:获取该属性的名称,查找map中是否有该名称的bean
		*                        如果有:执行注入
		*                        没有:获取该属性的类型 遍历map中判断是否有和该类型一致的bean
		* 
		*/
		for(String beanName : intsances.keySet()) {
			Object bean = intsances.get(beanName);
			if(bean != null) {
				try {
					PropertyDescriptor[] ps =  Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
					for(PropertyDescriptor propertyDesc : ps) {
						Method setter = propertyDesc.getWriteMethod();
						if(setter != null && setter.isAnnotationPresent(MyResource.class)) {
							MyResource myResource = setter.getAnnotation(MyResource.class);
							Object value = null;
							if(myResource.name() != null && !"".equals(myResource.name())) {
								value = intsances.get(myResource.name());
							}else {
								value = intsances.get(propertyDesc.getName());
								if(value == null) {
									for(String key : intsances.keySet()) {
										if(propertyDesc.getPropertyType().isAssignableFrom(intsances.get(key).getClass())) {
											value = intsances.get(key);
											break;
										}
									}
								}
							}
							setter.setAccessible(true);
							setter.invoke(bean, value);
						}
					
						Field[] fields = bean.getClass().getDeclaredFields();
						for(Field field : fields) {
							if(field.isAnnotationPresent(MyResource.class)) {
								MyResource myResource = field.getAnnotation(MyResource.class);
								Object value = null;
								if(myResource.name() != null && !"".equals(myResource.name())) {
									value = intsances.get(myResource.name());
								}else {
									value = intsances.get(field.getName());
									if(value == null) {
										for(String key : intsances.keySet()) {
											if(field.getType().isAssignableFrom(intsances.get(key).getClass())) {
												value = intsances.get(key);
												break;
											}
										}
									}
								}
								field.setAccessible(true);
								field.set(bean, value);
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
&nbsp;
	/**
	* 注入属性的值
	*/
	private void Injected() {
		for(BeanDefinition beanDefinition : beanDefinitions) {
			Object bean = intsances.get(beanDefinition.getId());
			if(bean != null) {
				try {
					//通过Java的内省机制获取到对象中所有属性的描述信息
					PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
					for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()) {
						for(PropertyDescriptor propertyDesc : ps) {
							//判断XML文件中解析出来的属性和对象中的属性名称是否一样
							if(propertyDefinition.getName().equals(propertyDesc.getName())) {
								//获取属性的setter方法
								Method setter = propertyDesc.getWriteMethod();
								if(setter != null) {
									Object value = null;
									//如果property中没有ref属性,那么表示后面将进行的是基本属性的装配
									if(propertyDefinition.getRef() != null && !"".equals(propertyDefinition.getRef().trim())) {
										value = intsances.get(propertyDefinition.getRef());
									}else {
										value = ConvertUtils.convert(propertyDefinition.getValue(), propertyDesc.getPropertyType());
									}
									setter.setAccessible(true);
									//调用对象的setter方法赋值
									setter.invoke(bean, value);
								}
								break;
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
&nbsp;
   /**
	* 通过反射获取bean的实例
	*/
	private void instanceBeans() {
		for(BeanDefinition beanDefinition : beanDefinitions) {
			try {
				if(beanDefinition.getClazz() != null && !"".equals(beanDefinition.getClazz())) {
					intsances.put(beanDefinition.getId(), Class.forName(beanDefinition.getClazz()).newInstance());
				}
			} catch (Exception e) {
				e.printStackTrace();
			} 
		}
	}
&nbsp;
	/**
	* 读取配置信息并将bean信息的描述对象存储到List中
	* @param configFileName
	*/
	@SuppressWarnings("unchecked")
	private void readConfig(String configFileName) {
		Document document=null; 
		Map<String,String> nsMap = new HashMap<String,String>();
		try{
			document = new SAXReader().read(this.getClass().getClassLoader().getResource(configFileName));
			nsMap.put("ns","http://www.springframework.org/schema/beans");    //加入命名空间
			XPath xsub = document.createXPath("//ns:beans/ns:bean");        //创建beans/bean查询路径
			xsub.setNamespaceURIs(nsMap);                                    //设置命名空间
			List<Element> beans = xsub.selectNodes(document);                //获取文档下所有bean节点 
			for(Element element: beans){
				String id = element.attributeValue("id");                    //获取id属性值
				String clazz = element.attributeValue("class");                //获取class属性值 
				BeanDefinition beanDefine = new BeanDefinition(id, clazz);
				XPath propertysub = element.createXPath("ns:property");        //设置命名空间
				propertysub.setNamespaceURIs(nsMap);
				List<Element> properties = propertysub.selectNodes(element);
				for(Element property : properties) {
					String propertyName = property.attributeValue("name");
					String propertyRef = property.attributeValue("ref");
					String propertyValue = property.attributeValue("value");
					PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyRef,propertyValue);
					beanDefine.getPropertys().add(propertyDefinition);
				}
				beanDefinitions.add(beanDefine);
			} 
		}catch(Exception e){ 
			e.printStackTrace();
		}
	}
	/**
	* 外界获取bean对象的接口
	*/
	public Object getBean(String beanName) {
		return this.intsances.get(beanName);
	}
}
  • 大小: 69.3 KB
分享到:
评论
1 楼 laiweiweihi 2011-12-17  
这代码必须得重构哇,博主.

相关推荐

    以注解方式模拟Spring IoC AOP

    本篇将深入探讨如何通过注解方式来模拟Spring的这两种机制,帮助你理解其底层原理。 ### 1. 依赖注入(IoC) 依赖注入是Spring框架的核心特性之一,它通过反转对象创建和管理的控制权,使得应用程序组件之间的耦合...

    spring依赖注入

    在Spring框架中,依赖注入主要通过两种方式实现:构造器注入和setter注入。构造器注入是在对象实例化时通过构造器传入依赖,而setter注入则是通过调用对象的setter方法来设置依赖。 1. **构造器注入**: 当类的...

    千锋最新版spring6.0框架GA版详解.pdf

    使用@Autowired、@Resource等注解进行依赖注入。 4. **注解开发管理第三方bean** 通过@ComponentScan注解扫描指定包下的bean,支持第三方库中的组件。 #### 五、AOT 1. **AOT概述** AOT(Ahead-Of-Time)...

    Spring Recipes A Problem-Solution Approach.pdf

    此外,还引入了更多的注解支持,例如`@Autowired`、`@Resource`等,使得开发者可以通过注解的方式进行依赖注入,而无需过多的手动配置。 2. **AOP增强**:Spring 2.5增强了对AOP的支持,提供了更加强大的切入点...

    模拟spring中的ClassPathXmlApplicationContext类的实现

    Spring框架是Java应用程序开发中的一个核心组件,它提供了一个依赖注入(DI)和面向切面编程(AOP)的解决方案。在Spring中,`ClassPathXmlApplicationContext`是用于加载和管理配置元数据的一个重要类,它允许我们...

    Spring的学习笔记

    **模拟Spring功能** 在学习Spring之前,可能需要理解如何手动管理对象的依赖关系。Spring通过IOC(控制反转)和DI(依赖注入)实现了对对象生命周期的管理,从而消除了手动管理的复杂性。 **搭建Spring运行环境** ...

    2023年ssm框架题库java.doc

    五、依赖注入的实现方式 1. **构造器注入**:通过构造函数传递依赖对象。 2. **setter方法注入**:通过setter方法设置依赖对象。 3. **接口注入**:组件实现特定的接口,由Spring通过接口方法注入依赖。 4. **注解...

    spring2.5 学习笔记

    #### 模拟Spring功能 在深入学习Spring之前,尝试手动实现Spring的部分功能,如依赖注入,可以加深对Spring工作原理的理解。这通常涉及到定义接口、实现类以及通过某种机制(如工厂模式)来管理对象的创建和依赖...

    spring2.5学习笔记以及SSH

    模拟Spring功能是指在不使用Spring框架的情况下,尝试实现Spring的核心特性,如依赖注入。这有助于理解Spring的工作原理,也方便在没有Spring环境的条件下学习和测试相关概念。 搭建Spring的运行环境包括创建新的...

    Spring的经典面试题

    - **易于测试**:Spring框架提供的测试支持使得测试变得更加简单,可以通过依赖注入轻松地模拟测试数据。 - **强大的Web框架**:Spring MVC框架为Web开发提供了灵活且强大的解决方案。 - **事务管理**:Spring提供了...

    Spring学习笔记

    依赖注入则是实现控制反转的一种方式,它通过在对象创建时,注入其依赖的对象,来实现耦合度的降低。 好处包括: - 解耦:对象之间不需要直接交互,降低了代码之间的耦合性。 - 可测试性:更容易编写单元测试,因为...

    Spring.NET学习笔记-控制反转

    2. **便于单元测试**:依赖注入使得我们可以很容易地替换掉真实依赖,用模拟对象(mocks)进行替代,从而方便地进行单元测试。 3. **易于维护**:依赖关系明确,修改或替换依赖时不会影响到其他模块。 #### 三、...

    struts2_spring3.0_Junit4.7_Maven2.2.1_整合运行说明_培训.pdf )

    ### 整合技术框架说明 本文档主要介绍了如何将Struts2、Spring3.0、JUnit4.7和Maven2.2.1这几种...此外,通过使用Spring作为依赖注入容器,我们能够更好地管理应用程序的组件,进一步提升了代码的灵活性和可扩展性。

    真正的中文Spring2.5 API 兴奋!

    Spring2.5在依赖注入(Dependency Injection,DI)方面进行了优化,使得配置更加简洁和灵活。它引入了注解驱动的配置,如`@Autowired`、`@Resource`和`@Component`等,允许开发者在不使用XML配置的情况下实现bean的...

    Spring面试

    依赖注入是IoC的一个具体实现,通过构造器注入、setter注入等方式,将对象的依赖关系在运行时动态地注入到对象中。 #### 6. BeanFactory与ApplicationContext - **BeanFactory**:是Spring中最基本的容器,提供依赖...

    Spring2.5开发简明教程中文版

    Spring是一个开源的企业级Java应用程序框架,它通过依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)简化了Java开发。在Spring 2.5中,DI得到了进一步强化,使得配置更加...

Global site tag (gtag.js) - Google Analytics