模拟spring的依赖注入原理

1,依赖注入的实现代码

package junit.test;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
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 joeho.vo.BeanDefinition;
import joeho.vo.PropertyDefinition;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;


public class JoehoaClassPathXMLApplicationContext {
 private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
 private Map<String,Object> singeton = new HashMap<String,Object>();
 
 
 public JoehoaClassPathXMLApplicationContext(String xmlName) {
  this.readXml(xmlName);
  this.instanceBeans();
  this.injectObject();
 }

 /**
  * 读XML文件
  * @param xmlName
  */
 private void readXml(String xmlName) {
  SAXReader saxReader = new SAXReader();
  Document document = null;
  
  try {
   URL xmlPath = this.getClass().getClassLoader().getResource(xmlName);
   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> list = xsub.selectNodes(document);//获取文档下的所有BEAN节点
   
   for(Element element:list){
    String id = element.attributeValue("id");//获取ID属性值
    String classzz = element.attributeValue("class");//获取class属性值
    BeanDefinition beanDefin = new BeanDefinition(id,classzz);
    
    XPath xsubproperty = element.createXPath("ns:property");//创建bean/property的查询路径
    xsubproperty.setNamespaceURIs(nsMap);//设置命名空间
    List<Element> propertys = xsubproperty.selectNodes(element);//获取文档下的所有property节点
    for(Element property:propertys){
     String propertyname = property.attributeValue("name");
     String propertyref = property.attributeValue("ref"); 
     PropertyDefinition propertyBean = new PropertyDefinition(propertyname,propertyref);
     beanDefin.getPropertys().add(propertyBean);
    }
    beanDefines.add(beanDefin);
   }
      
  } catch (DocumentException e) {
   e.printStackTrace();
  } 
  
 }
 /**
  * 完成bean的实例化
  */
 private void instanceBeans() {

  for(BeanDefinition beans:beanDefines){
   try {
    if(beans.getClasszz()!=null&&!"".equals(beans.getClasszz().trim())){
     singeton.put(beans.getId(), Class.forName(beans.getClasszz()).newInstance());
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
  
 }
 
 
 /**
  * 为bean的属性注入值
  * 注入的原理
  */
 private void injectObject() {
  for(BeanDefinition beanDefine:beanDefines ){
   Object bean = singeton.get(beanDefine.getId());//获取实例对象
   if(bean!=null){
    try {
     PropertyDescriptor[] beanProperty = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
     for(PropertyDefinition propertyDefini:beanDefine.getPropertys()){
      //获取property的所有属性,并和beanProperty中的属性进行比较
      for(PropertyDescriptor propertyDes:beanProperty){
       if(propertyDefini.getName().equals(propertyDes.getName())){
        Method setter =propertyDes.getWriteMethod();//获取属性的setter方法
        if(setter!=null){
         Object value = singeton.get(propertyDefini.getRef());//从容器中取得XML中的ref对象
         setter.setAccessible(true);//可能为私有的则不能访问,为了能访问设置为TRUE
         setter.invoke(bean, value);//把引用对象注入到属性
        }
        break;
       }
      }
      
     }
    } catch (Exception e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    
   }
  
  }
  
 }
 /**
  * 获取Bean实例
  * @param beanName
  * @return
  */
 public Object getBean(String beanName){
  return singeton.get(beanName);
 }
}

2,引用的BEAN对象

package joeho.vo;

import java.util.ArrayList;
import java.util.List;

public class BeanDefinition {
 private String id;
 private String classzz;
 private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>();
 
 public BeanDefinition(String id, String classzz) {
  this.id = id;
  this.classzz = classzz;
 }
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getClasszz() {
  return classzz;
 }
 public List<PropertyDefinition> getPropertys() {
  return propertys;
 }
 public void setPropertys(List<PropertyDefinition> propertys) {
  this.propertys = propertys;
 }
 public void setClasszz(String classzz) {
  this.classzz = classzz;
 }
 
}

package joeho.vo;

public class PropertyDefinition {
 private String name;
 private String ref;
 
 public PropertyDefinition(String name, String ref) {
  this.name = name;
  this.ref = ref;
 }
 
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getRef() {
  return ref;
 }
 public void setRef(String ref) {
  this.ref = ref;
 }
 
}

3,解析的XML

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
          
        <!-- Bean service -->
  <bean id="personservice" class="joeho.blog.service.impl.PersonServiceBean" destroy-method="delete" >
   <!-- 此处的name属性填的是service类中setter的属性值,ref引用的是bean dao中的对象,此处将ref中的对象注入到属性中来 -->
   <property name="personDao" ref="personDao"></property>  
  </bean>
  <bean id="personservice1" class="joeho.blog.service.impl.PersonServiceBeanFactory" factory-method="createPersonServiceBean1"/>
  <bean id="PersonServiceBeanFactory" class="joeho.blog.service.impl.PersonServiceBeanFactory" />
  <bean id="personservice2" factory-bean="PersonServiceBeanFactory" factory-method="createPersonServiceBean2"></bean>
  <!-- bean dao -->
  <bean id="personDao" class="joeho.blog.dao.impl.PersonDaoBean"></bean>
  
</beans>

 

4,JUNIT测试代码

package junit.test;


import joeho.blog.service.PersonService;

import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest {

 @BeforeClass
 public static void setUpBeforeClass() throws Exception {
 }

 @Test
 public void instanceSpring(){
/*  AbstractApplicationContext act = new ClassPathXmlApplicationContext("Beans.xml");
  PersonService ps=(PersonService)act.getBean("personservice");
  PersonService ps1=(PersonService)act.getBean("personservice1");
  System.out.println(ps==ps1);
  ps.save();
  act.close();*/
  JoehoaClassPathXMLApplicationContext act = new JoehoaClassPathXMLApplicationContext("Beans.xml");
  PersonService ps=(PersonService)act.getBean("personservice");
  ps.save();
  
 }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值