spring控制反转与依赖注入

 

 

 所用的环境 :dom4j  spring 2.5.6 ,用的有:spring.jar dom4j.jar common-logging.jar

采用Junit-4对应用进行单元测试。并且采用面向接口编程(抽象出接口层)

 

Spring的配置文件:beans.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,实现控制反转,即由spirng容器负责创建对象-->
    <bean id="personService" class="com.sgl.imp.PersonServiceBean" ></bean>
  
    <!--通过set方法进行依赖注入-->
 
   <bean id="daoPerson" class="com.sgl.dao.imp.PersonDaoBean"></bean>
    <bean id="personService4" class="com.sgl.imp.PersonServiceBean">
        <property name="personDao" ref="daoPerson"></property>
    </bean>
  
</beans>

 

所用到java源文件如下 :

1、自定义应用上下文(核心)


package sgl.spring.principle;

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 java.util.logging.Level;
import java.util.logging.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

/**
 *
 * @author administrator
 */
public class SglClassPathXmlApplicationContext {

    private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();//存放所有的bean实例
    private Map<String, Object> sinletons = new HashMap<String, Object>();//存放bean与之相关联的类实例的映射

    public SglClassPathXmlApplicationContext(String fileName) {
        this.readXml(fileName);
        this.instanceBeans();
        this.injectObject();
    }

    /**
     * 读取xml配置文件
     * @param fileName 配置文件名
     */
    private void readXml(String fileName) {
        SAXReader saxReader = new SAXReader();
        Document document = null;

        URL xmlPath = this.getClass().getClassLoader().getResource(fileName);
        try {
            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");//获取bean 的id属性
                String className = element.attributeValue("class");//获取bean的class属性
                XPath propertyPath = element.createXPath("ns:property");//创建bean/property查询路径
                propertyPath.setNamespaceURIs(nsMap);//设置命名空间和根元素一致
                List<Element> propertys = propertyPath.selectNodes(element);//取得element(即bean)下所有property

                BeanDefinition beanDefine = new BeanDefinition(id, className);//实例化一个bean
                //设置property的属性,因为可能有多个property,所以用循环
                for (Element property : propertys) {
                    String name = property.attributeValue("name");//获得property的name属性
                    String ref = property.attributeValue("ref");//获得property的ref属性
                    System.out.println("" + name + " " + ref);
                    PropertyDefinition propertyDefine = new PropertyDefinition(name, ref);
                    beanDefine.getPropertys().add(propertyDefine);
                }
                beanDefines.add(beanDefine);//将bean实例加入数组中
            }


        } catch (Exception ex) {
            Logger.getLogger(SglClassPathXmlApplicationContext.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * 完成bean实例化
     */
    private void instanceBeans() {
        System.out.println("实例化开始");
        for (BeanDefinition beanDefine : beanDefines) {
            if (beanDefine.getClassName() != null && !"".equals(beanDefine.getClassName().trim())) {
                try {
                    //利用java反射技术来取得java类实例
                    System.out.println("beanID " + beanDefine.getId());
                    sinletons.put(beanDefine.getId(), Class.forName(beanDefine.getClassName()).newInstance());
                } catch (Exception ex) {
                    Logger.getLogger(SglClassPathXmlApplicationContext.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        System.out.println("实例化结束");
    }

    /**
     * 获取bean实例
     * @param beanName
     * @return
     */
    public Object getBean(String beanName) {
        return this.sinletons.get(beanName);
    }

    private void injectObject() {
        for (BeanDefinition beanDefine : beanDefines) {//遍历所有的<bean>,因为所有的<bean>右能都有property属性
            Object bean = getBean(beanDefine.getId());//由bean的id,取得bean实例
            if (bean != null) {
                try {
                    //如果从<property>中取出的属性(存储在name字段中)在<bean>所对应类的属性(字段),也就是说我们一定人保证
                    //<property name="属性"………………>中的“属性”在<bean>所指向类中有对应的定义

                    //取得bean对应类的所有属性的描述(即bean类定义的所有字段)
                    PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
                 
                    for (PropertyDefinition property : beanDefine.getPropertys()) {//一个bean可以有多个<property>
                        //PropertyDescriptor中有很多字段,找出与<property name="属性">所对应的字段
                        for (PropertyDescriptor propertyDes : ps) {//propertyDes是<bean>所指向类的定义字段的描述
                            System.out.println("ps "+propertyDes.getName());
                            //如果property的name字段在<bean>有对应字段的定义,就进行注入
                            if (property.getName().equals(propertyDes.getName())) {
                                //根据propety中的ref属性进行依赖


                                //取得当前bean类的property属性的name属性对应值的属性(在此指personDao)setter方法
                                Method setter = propertyDes.getWriteMethod();
                                //取得ref对应类实例
                                if (setter != null) {                              
                                    Object value = sinletons.get(property.getRef());
                                    setter.setAccessible(true);//让私有方法变得透明
                                    setter.invoke(bean, value);
                                }

                                break;//找到对应属性,其它的属性不用比较
                            }
                        }
                    }
                } catch (Exception ex) {
                    Logger.getLogger(SglClassPathXmlApplicationContext.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
}

 

2、PersonDao.java(接口程序)

 


package com.sgl.dao;
public interface PersonDao {

    void add();

}

 

3、PersonDaoBean.java(接口层实现程序)
package com.sgl.dao.imp;
import com.sgl.dao.PersonDao;
public class PersonDaoBean implements PersonDao {
    public void add(){
        System.out.println("执行PersonDaoBean中add()方法");
    }

}


4、 PersonService.java(业务层接口)


package com.sgl;
public interface PersonService {

    void save();  

    void save2();



}

 

 

5、PersonServiceBean.java(业务层实现程序)


package com.sgl.imp;
import com.sgl.PersonService;
import com.sgl.dao.PersonDao;


public class PersonServiceBean implements PersonService {
    private PersonDao personDao;

    public void save(){
        System.out.println("我是PersonServiceBean中的save()方法");
        personDao.add();
    }

 

public void save2(){
        System.out.println("这是PersonServiceBean中的Save2方法");
    }

    public void setPersonDao(PersonDao personDao) {
        this.personDao = personDao;
    }

}

 

6配置文件中,对应属性的类封装( id、class、property)

 

 1)、BeanDefinition.java



package sgl.spring.principle;

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


public class BeanDefinition {
    private String id;
    private String className;
    private List<PropertyDefinition> propertys=new  ArrayList<PropertyDefinition>();

    public BeanDefinition() {
    }
    public BeanDefinition(String id, String className) {
        this.id = id;
        this.className = className;
    }

  
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getClassName() {
        return className;
    }
    public void setClassName(String className) {
        this.className = className;
    }

    public List<PropertyDefinition> getPropertys() {
        return propertys;
    }

    public void setPropertys(List<PropertyDefinition> propertys) {
        this.propertys = propertys;
    } 
}

 

2)、PropertyDefinition.java(<property>的定义)


package sgl.spring.principle;


public class PropertyDefinition {
    private String name;
    private String ref;

    public PropertyDefinition(String name, String ref) {
        this.name = name;
        this.ref = ref;
    }

    public PropertyDefinition() {
    }
  
    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;
    }

}

 

7、单元测试类文件 SglSpringTest.java,是junit-4.x

 

 


package junit.test;

import com.sgl.PersonService;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import sgl.spring.principle.SglClassPathXmlApplicationContext;


public class SglSpringTest {

    public SglSpringTest() {
    }

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

    @AfterClass
    public static void tearDownClass() throws Exception {
    }

    @Before
    public void setUp() {
    }

    @After
    public void tearDown() {
    }

 
     @Test
     public void instanceBeans() {
     SglClassPathXmlApplicationContext ctx=new SglClassPathXmlApplicationContext("beans.xml");
     //测试控制反转,即由容器创建对象
     PersonService personService=(PersonService)ctx.getBean("personService");
     personService.save2();
     //测试控制反转和依赖注入
     PersonService personService4=(PersonService)ctx.getBean("personService4");
     personService4.save();
     }
   

}

 

你可能感兴趣的:(spring,exception,bean,String,object,Class)