`
忘忧鸟
  • 浏览: 144845 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

理解Spring依赖注入(模拟Spring容器)

阅读更多

仿spring容器 ,也就是传智播客容器 ItcastClassPathXMLApplicationContext

import java.beans.Introspector;   
import java.beans.PropertyDescriptor;   
import java.lang.reflect.Field;   
import java.lang.reflect.Method;   
import java.net.URL;   
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 ItcastClassPathXMLApplicationContext {   
    private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();   
    private Map<String, Object> sigletons = new HashMap<String, Object>();   
       
    public ItcastClassPathXMLApplicationContext(String filename){   
        this.readXML(filename);   
        this.instanceBeans();   
        this.annotationInject();   
        this.injectObject();   
    }   
    /**  
     * 通过注解实现注入依赖对象  
     */   
    private void annotationInject() {   
        for(String beanName : sigletons.keySet()){   
            Object bean = sigletons.get(beanName);   
            if(bean!=null){   
                try {   
                    PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();   
                    for(PropertyDescriptor properdesc : ps){   
                        Method setter = properdesc.getWriteMethod();//获取属性的setter方法   
                        /*如果setter方法不为空,并且上面有注解*/   
                        if(setter!=null && setter.isAnnotationPresent(ItcastResource.class)){   
                            /*得到注解*/   
                            ItcastResource resource = setter.getAnnotation(ItcastResource.class);   
                            Object value = null;   
                            //如果注解的name属性不为空,也就是这种情况    @ItcastResource(name="persionDao")   
                            if(resource.name()!=null && !"".equals(resource.name())){   
                                value = sigletons.get(resource.name());   
                            }else{   
                            /*如果注解的name为空,则根据属性的名字来得到bean*/   
                                value = sigletons.get(properdesc.getName());   
                                if(value==null)   
                                {   
                                    /*如果的得到的bean为空,则根据key遍历容器中所有的bean,如果发现和属性类型相同的bean,就开始注入*/   
                                    for(String key : sigletons.keySet()){   
                                        if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){   
                                            value = sigletons.get(key);   
                                            break;   
                                        }   
                                    }   
                                }                                  
                            }   
                            setter.setAccessible(true);   
                            setter.invoke(bean, value);//把引用对象注入到属性   
                        }   
                    }   
                    /*对字段处理,也就是字段上有注解的情况*/   
                    Field[] fields = bean.getClass().getDeclaredFields();   
                    for(Field field : fields){   
                        if(field.isAnnotationPresent(ItcastResource.class)){   
                            ItcastResource resource = field.getAnnotation(ItcastResource.class);   
                            Object value = null;   
                            if(resource.name()!=null && !"".equals(resource.name())){   
                                value = sigletons.get(resource.name());   
                            }else{   
                                value = sigletons.get(field.getName());   
                                if(value==null){   
                                    for(String key : sigletons.keySet()){   
                                        if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){   
                                            value = sigletons.get(key);   
                                            break;   
                                        }   
                                    }   
                                }                                  
                            }   
                            field.setAccessible(true);//允许访问private字段   
                            field.set(bean, value);   
                        }   
                    }   
                } catch (Exception e) {   
                    e.printStackTrace();   
                }   
            }   
        }   
    }   
  
    /**  
     * 为bean对象的属性注入值  
     */   
    private void injectObject() {   
        for(BeanDefinition beanDefinition : beanDefines){   
            Object bean = sigletons.get(beanDefinition.getId());   
            if(bean!=null){   
                try {   
                    PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();   
                    for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()){   
                        for(PropertyDescriptor properdesc : ps){   
                            if(propertyDefinition.getName().equals(properdesc.getName())){   
                                Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private   
                                if(setter!=null){   
                                    Object value = null;   
                                    if(propertyDefinition.getRef()!=null && !"".equals(propertyDefinition.getRef().trim())){   
                                        value = sigletons.get(propertyDefinition.getRef());   
                                    }else{   
                                        value = ConvertUtils.convert(propertyDefinition.getValue(), properdesc.getPropertyType());   
                                    }   
                                    setter.setAccessible(true);   
                                    setter.invoke(bean, value);//把引用对象注入到属性   
                                }   
                                break;   
                            }   
                        }   
                    }   
                } catch (Exception e) {   
                }   
            }   
        }   
    }   
    /**  
     * 完成bean的实例化  
     */   
    private void instanceBeans() {   
        for(BeanDefinition beanDefinition : beanDefines){   
            try {   
                if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim()))   
                    sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());   
            } catch (Exception e) {   
                e.printStackTrace();   
            }   
        }   
           
    }   
    /**  
     * 读取xml配置文件  
     * @param filename  
     */   
    private void readXML(String filename) {   
           SAXReader saxReader = new SAXReader();      
            Document document=null;      
            try{   
             URL xmlpath = this.getClass().getClassLoader().getResource(filename);   
             document = saxReader.read(xmlpath);   
             Map<String,String> nsMap = new HashMap<String,String>();   
             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> propertys = propertysub.selectNodes(element);   
                for(Element property : propertys){                     
                    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);   
                }   
                beanDefines.add(beanDefine);   
             }    
            }catch(Exception e){      
                e.printStackTrace();   
            }   
    }   
    /**  
     * 获取bean实例  
     * @param beanName  
     * @return  
     */   
    public Object getBean(String beanName){   
        return this.sigletons.get(beanName);   
    }   
}   

 

  测试:
ItcastClassPathXMLApplicationContext ctx = new ItcastClassPathXMLApplicationContext("beans.xml");
PersionSevice ps=(PersionSevice)ctx.getBean("persionServiceBean");
ps.save();

分享到:
评论

相关推荐

    模拟spring依赖注入

    模拟Spring的依赖注入,旨在理解其核心机制,让我们一起深入探讨这一主题。 首先,我们要明白什么是依赖注入。在传统的编程中,一个对象通常会直接创建或查找它所依赖的对象,这会导致类之间的紧密耦合。依赖注入则...

    使用反射和注解模拟Spring的依赖注入

    模拟Spring的依赖注入,我们可以创建一个简单的容器类,它使用反射来扫描带有特定注解的类,并根据这些注解管理bean。以下步骤概括了这个过程: 1. **定义注解**:创建自定义注解,如`@MyComponent`,用于标记需要...

    模拟Spring的依赖注入

    在模拟Spring的依赖注入时,我们可以创建一个类似于Spring容器的类,负责创建和管理对象以及它们的依赖关系。这个类可以包含一个注册方法,用于接收需要注入的对象及其依赖,然后在创建对象时进行注入。 **创建模拟...

    自己的代码模拟spring的依赖注入

    现在,我们将深入探讨如何通过自己的代码来模拟Spring的依赖注入。 首先,理解依赖注入的概念至关重要。依赖注入意味着组件不直接创建其依赖的对象,而是由外部实体(如Spring IoC容器)提供。这样做的好处是,我们...

    Spring简单模拟Spring容器

    标题中的“Spring简单模拟Spring容器”意味着我们将探讨Spring框架的核心特性——IoC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入),以及如何通过编程方式模拟Spring容器的工作原理。...

    Spring依赖注入原理解析.doc

    Spring依赖注入机制,也被称为控制反转(Inversion of Control,IOC),是Spring框架的核心特性,它使得应用程序的组件之间能够实现松散耦合。在传统编程中,对象通常自行创建和管理它们所依赖的其他对象,而在...

    Spring 依赖注入

    Spring框架是一个广泛使用的Java平台开发框架,其中心组件之一是其依赖注入容器。 - **Spring的IOC容器**:Spring的IoC容器是负责管理和控制对象生命周期的核心组件。它通过解析配置文件(通常是XML文件或注解)来...

    Spring中依赖注入与容器

    这样,业务逻辑组件无需关心依赖的具体实现,只需声明需要的服务,由Spring容器负责创建和注入。 通过这样的设计,Spring使得开发者可以更加专注于业务逻辑,而不是如何管理和创建依赖,从而提高了开发效率和代码...

    Spring容器的通俗理解及简单写法

    在Java开发中,Spring容器(也称为ApplicationContext或BeanFactory)扮演着重要角色,它通过控制反转(Inversion of Control, IOC)和依赖注入(Dependency Injection, DI)的概念,帮助开发者构建松散耦合的系统。...

    spring依赖注入

    Spring依赖注入是Java开发中的核心概念,特别是在使用Spring框架时,它是实现松耦合和可测试性的重要机制。依赖注入(Dependency Injection,简称DI)允许我们解耦组件之间的关系,使得代码更易于维护和扩展。它通过...

    Spring.Net依赖注入例子

    首先,依赖注入的基本思想是,对象不应该自行创建或查找其依赖的对象,而是应该由外部容器(如Spring.NET的ApplicationContext)在运行时提供这些依赖。这样,对象只需要关注自身的核心业务逻辑,而无需关心依赖对象...

    使用xml和annotation实现类似spring依赖注入和自动扫描类的功能

    现在,我们已经理解了XML配置和注解在实现依赖注入和自动扫描类中的作用。通过这些机制,我们可以轻松地管理类之间的关系,使代码更易于测试和维护。在实际项目中,通常结合使用XML和注解,以充分利用两者的优势。...

    简单Spring容器实现

    - **依赖注入(Dependency Injection, DI)**:Spring的核心特性,它允许外部环境(如Spring容器)来管理对象的创建和依赖关系。DI通过反转控制权,使得组件之间松耦合,易于测试和维护。 - **Bean工厂(Bean ...

    Spring的本质系列(1)依赖注入共3页.pdf.zip

    Spring框架是Java开发中不可或缺的一部分,它以其强大的依赖注入(Dependency...通过本文的介绍,相信你对Spring依赖注入有了更深入的理解。在实际开发中,灵活运用这些知识,可以让你的项目更加健壮、易于扩展和维护。

    自己动手模拟spring

    在模拟Spring的过程中,我们需要理解如何设计接口和实现类,以及如何通过容器来管理这些对象并负责它们之间的依赖关系。DI通常通过构造器注入、设值注入和接口注入等方式实现。 2. **组件扫描(Component Scanning...

    模拟Spring的IOC

    理解并模拟Spring的IOC机制对于深入学习Spring以及提升软件设计能力具有重要意义。 **1. 控制反转(IOC)概念** 控制反转是一种设计思想,它将对象的创建和管理权交给容器,而不是由对象自身负责。这样可以降低对象...

    模拟Spring的IoC容器实现注解自动装配

    在Spring框架中,IoC(Inversion of Control)容器是其核心特性之一,它负责管理对象的生命周期和依赖关系。IoC容器通过控制反转的概念...通过这样的实践,我们可以更深入地理解和掌握IoC容器以及注解驱动的依赖注入。

    Spring简单仿写,实现基本IOC,依赖注入和AOP 未解决循环依赖

    你需要模拟Spring容器的行为,管理bean的生命周期,处理依赖注入,并且确保在遇到循环依赖时能够优雅地处理。这涉及到对Java反射机制的理解,以及如何通过设计模式来解耦代码。 在压缩包文件"spring-Imitation"中,...

    自定义ioc容器,spring ioc容易模拟程序

    总的来说,自定义IOC容器是一个深入理解依赖注入和Spring框架的好方法。它可以帮助我们更好地掌握控制反转的概念,以及容器如何管理对象的生命周期和依赖关系。实践自定义容器不仅可以增强我们的编程技巧,也为将来...

    简单模拟springIoc容器

    在`YQIoc`这个压缩包中,可能包含了实现简单模拟Spring IoC容器的代码。通常,这个模拟会包含以下几个部分: 1. **Bean定义**:这是描述对象如何创建和配置的数据结构。在我们的例子中,bean定义可能是以XML形式...

Global site tag (gtag.js) - Google Analytics