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(); } /** * 注解实现依赖注入 */ 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(); } } } } /** * 注入属性的值 */ 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(); } } } } /** * 通过反射获取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(); } } } /** * 读取配置信息并将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); } }
相关推荐
本篇将深入探讨如何通过注解方式来模拟Spring的这两种机制,帮助你理解其底层原理。 ### 1. 依赖注入(IoC) 依赖注入是Spring框架的核心特性之一,它通过反转对象创建和管理的控制权,使得应用程序组件之间的耦合...
在Spring框架中,依赖注入主要通过两种方式实现:构造器注入和setter注入。构造器注入是在对象实例化时通过构造器传入依赖,而setter注入则是通过调用对象的setter方法来设置依赖。 1. **构造器注入**: 当类的...
使用@Autowired、@Resource等注解进行依赖注入。 4. **注解开发管理第三方bean** 通过@ComponentScan注解扫描指定包下的bean,支持第三方库中的组件。 #### 五、AOT 1. **AOT概述** AOT(Ahead-Of-Time)...
此外,还引入了更多的注解支持,例如`@Autowired`、`@Resource`等,使得开发者可以通过注解的方式进行依赖注入,而无需过多的手动配置。 2. **AOP增强**:Spring 2.5增强了对AOP的支持,提供了更加强大的切入点...
Spring框架是Java应用程序开发中的一个核心组件,它提供了一个依赖注入(DI)和面向切面编程(AOP)的解决方案。在Spring中,`ClassPathXmlApplicationContext`是用于加载和管理配置元数据的一个重要类,它允许我们...
**模拟Spring功能** 在学习Spring之前,可能需要理解如何手动管理对象的依赖关系。Spring通过IOC(控制反转)和DI(依赖注入)实现了对对象生命周期的管理,从而消除了手动管理的复杂性。 **搭建Spring运行环境** ...
五、依赖注入的实现方式 1. **构造器注入**:通过构造函数传递依赖对象。 2. **setter方法注入**:通过setter方法设置依赖对象。 3. **接口注入**:组件实现特定的接口,由Spring通过接口方法注入依赖。 4. **注解...
#### 模拟Spring功能 在深入学习Spring之前,尝试手动实现Spring的部分功能,如依赖注入,可以加深对Spring工作原理的理解。这通常涉及到定义接口、实现类以及通过某种机制(如工厂模式)来管理对象的创建和依赖...
模拟Spring功能是指在不使用Spring框架的情况下,尝试实现Spring的核心特性,如依赖注入。这有助于理解Spring的工作原理,也方便在没有Spring环境的条件下学习和测试相关概念。 搭建Spring的运行环境包括创建新的...
- **易于测试**:Spring框架提供的测试支持使得测试变得更加简单,可以通过依赖注入轻松地模拟测试数据。 - **强大的Web框架**:Spring MVC框架为Web开发提供了灵活且强大的解决方案。 - **事务管理**:Spring提供了...
依赖注入则是实现控制反转的一种方式,它通过在对象创建时,注入其依赖的对象,来实现耦合度的降低。 好处包括: - 解耦:对象之间不需要直接交互,降低了代码之间的耦合性。 - 可测试性:更容易编写单元测试,因为...
2. **便于单元测试**:依赖注入使得我们可以很容易地替换掉真实依赖,用模拟对象(mocks)进行替代,从而方便地进行单元测试。 3. **易于维护**:依赖关系明确,修改或替换依赖时不会影响到其他模块。 #### 三、...
### 整合技术框架说明 本文档主要介绍了如何将Struts2、Spring3.0、JUnit4.7和Maven2.2.1这几种...此外,通过使用Spring作为依赖注入容器,我们能够更好地管理应用程序的组件,进一步提升了代码的灵活性和可扩展性。
Spring2.5在依赖注入(Dependency Injection,DI)方面进行了优化,使得配置更加简洁和灵活。它引入了注解驱动的配置,如`@Autowired`、`@Resource`和`@Component`等,允许开发者在不使用XML配置的情况下实现bean的...
依赖注入是IoC的一个具体实现,通过构造器注入、setter注入等方式,将对象的依赖关系在运行时动态地注入到对象中。 #### 6. BeanFactory与ApplicationContext - **BeanFactory**:是Spring中最基本的容器,提供依赖...
Spring是一个开源的企业级Java应用程序框架,它通过依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)简化了Java开发。在Spring 2.5中,DI得到了进一步强化,使得配置更加...