MyException - 我的异常网
当前位置:我的异常网» 编程 » Spring安装基本属性的原理分析与代码实现

Spring安装基本属性的原理分析与代码实现

www.MyException.Cn  网友分享于:2013-11-20  浏览:2次
Spring装配基本属性的原理分析与代码实现

首先,做一个配置属性的基本测试。修改beans.xml,使引用外部类变成内部bean属性:

<?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 id="peopleDao" class="com.wxy.dao.impl.PeopleDaoBean"></bean>

         <bean id="peopleService" class="com.wxy.service.impl.PeopleServiceBean">

                  <property name="peopleDao" ref=” peopleDao”/>

                 

         </bean>

</beans>

 

  测试:

public class Test {

 

    public static void main(String[] args) {

        //IOC容器实例化

        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");

        PeopleService peopleService = (PeopleService) ac.getBean("peopleService");

        peopleService.save();

    }

 

}

    结果正常!能够引用得到(这不是废话么) 

   使用refref所指向的bean可以被多个bean引用;ref依赖对象将作为一个属性被注入。

  

 

Spring是如何实现装配基本属性的呢?下面用源码模拟实现之:

 

1 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 id="peopleDao" class="com.wxy.dao.impl.PeopleDaoBean"></bean>-->

         <bean id="peopleService" class="com.wxy.service.impl.PeopleServiceBean">

                    <property name="peopleDao" ref="com.wxy.dao.impl.PeopleDaoBean"/>

                    <property name="name" value="wxy"/>

                    <property name="id" value="218"/>

         </bean>

</beans>

    

2、在属性BeanPorpertyDefinition中定义相应的属性,用来存放xml文件中定义的属性:

package com.wxy.bean;

 

/**

*   存放beanproperty属性

* 

*   @creator            xiaoyu.wang  

*   @create-time     2011-8-10   下午04:40:07  

*   @revision          $Id

*/

public class PropertyDefinition {

 

    private String name; //属性名

    private String ref;  //属性依赖对象

    private String value;

 

    /**

     * @return the name

     */

    public String getName() {

        return name;

    }

 

    /**

     * @param name the name to set

     */

    public void setName(String name) {

        this.name = name;

    }

 

    /**

     * @return the ref

     */

    public String getRef() {

        return ref;

    }

 

    /**

     * @param ref the ref to set

     */

    public void setRef(String ref) {

        this.ref = ref;

    }

 

    public PropertyDefinition(String name, String ref, String value) {

        super();

        this.name = name;

        this.ref = ref;

        this.value = value;

    }

 

    /**

     * @return the value

     */

    public String getValue() {

        return value;

    }

 

    /**

     * @param value the value to set

     */

    public void setValue(String value) {

        this.value = value;

    }

 

    /* (non-Javadoc)

     * @see java.lang.Object#toString()

     */

    @Override

    public String toString() {

        return "PropertyDefinition [name=" + name + ", ref=" + ref + ", value=" + value + "]";

    }

 

}

   

3 修改PeopelServiceBean ,添加相对应的属性:

 public class PeopleServiceBean implements PeopleService {

 

    private PeopleDao peopleDao;

    private String    name;

    private Integer   id;

 

    /**

     * @return the peopleDao

     */

    public PeopleDao getPeopleDao() {

        return peopleDao;

    }

 

    /**

     * @param peopleDao the peopleDao to set

     */

    public void setPeopleDao(PeopleDao peopleDao) {

        this.peopleDao = peopleDao;

    }

 

    /**

     * @return the name

     */

    public String getName() {

        return name;

    }

 

    /**

     * @param name the name to set

     */

    public void setName(String name) {

        this.name = name;

    }

 

    /**

     * @return the id

     */

    public Integer getId() {

        return id;

    }

 

    /**

     * @param id the id to set

     */

    public void setId(Integer id) {

        this.id = id;

    }

 

    public void save() {

 

        System.out.println("--> the method is called save()! name=" + name + ",id=" + id);

        peopleDao.add();

    }

 

}

  

4、读取属性值,修改WxyClassPathXMLApplicationContext.java, 添加注入属性功能  

package com.wxy.content;

 

import java.beans.IntrospectionException;

import java.beans.Introspector;

import java.beans.PropertyDescriptor;

import java.lang.reflect.InvocationTargetException;

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;

 

import com.wxy.bean.BeanDefinition;

import com.wxy.bean.PropertyDefinition;

 

/**

*  自定义IoC容器

*  BeanDefinitionresource定位:readXML();

*  BeanDefinition的载入和解析 :readXML();

*  BeanDefinitionIoC容器中的注册 instanceBeans();

*   @create-time     2011-8-10   上午09:19:17  

*   @revision          $Id

*/

public class WxyClassPathXMLApplicationContext {

 

    //存放BeanDefinition的列表,在beans.xml中定义的bean可能不止一个

    private final List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();

    //将类名作为索引,将创建的Bean对象存入到Map

    private final Map<String, Object>  sigletons   = new HashMap<String, Object>();

 

    public WxyClassPathXMLApplicationContext(String fileName) {

        //读取xml配置文件

        this.readXML(fileName);

        //实例化bean

        this.instanceBeans();

        //注入对象

        this.injectObject();

    }

 

    /**

     *bean对象的属性注入值

     */

    private void injectObject() {

        for (BeanDefinition beanDefinition : beanDefines) {

            //获取beanDefines中的对象

            Object bean = sigletons.get(beanDefinition.getId());

            if (bean != null) {

                //如果存在,利用反射技术将值注入

                try {

                    //获取Bean的描述属性类

                    PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass())

                        .getPropertyDescriptors();

                    for (PropertyDefinition propertyDefinition : beanDefinition.getProperties()) {

                        for (PropertyDescriptor properdesc : ps) {

                            //取得属性名字与propertyDefinition中的属性做比较

                            if (propertyDefinition.getName().equals(properdesc.getName())) {

                                //获得属性的setter方法

                                Method setter = properdesc.getWriteMethod();

                                if (setter != null) {

 

                                    Object value = null;

                                    if (propertyDefinition.getRef() != null

                                        && !propertyDefinition.getRef().isEmpty()) {//注入依赖对象

                                        value = sigletons.get(propertyDefinition.getRef());

                                    } else {//注入基本类型

                                        //将字符串类型装换成用户需要的类型,需要用到jar包中的commons-beanutils.jar

                                        value = ConvertUtils.convert(propertyDefinition.getValue(),

                                            properdesc.getPropertyType());

                                    }

                                    //允许访私有方法

                                    setter.setAccessible(true);

                                    //把引用对象注入到属性

                                    setter.invoke(bean, value);

                                }

                            }

                        }

                    }

                } catch (SecurityException e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

                } catch (IllegalArgumentException e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

                } catch (IntrospectionException e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

                } catch (IllegalAccessException e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

                } catch (InvocationTargetException e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

                }

            }

        }

    }

 

    /**

     * 读取XML配置文件,获取BeanDefinition内容,存入到beanDefinition列表中

     * @param fileName xml配置文件名称

     */

 

    private void readXML(String fileName) {

        SAXReader saxReader = new SAXReader();

        Document document = null;

        try {

            //通过类加载器获取Resource资源路径,实现BeanDefinitionresource定位

            URL xmlPath = this.getClass().getClassLoader().getResource(fileName);

            //xml读入到document

            document = saxReader.read(xmlPath);

            Map<String, String> nsMap = new HashMap<String, String>();

            //加入命名空间

            nsMap.put("ns", "http://www.springframework.org/schema/beans");

            //创建beans/bean查询路径,注意:路径前要注明命名空间,便于解析

            XPath xsub = document.createXPath("//ns:beans/ns:bean");

            //设置命名空间

            xsub.setNamespaceURIs(nsMap);

            //获取文档下的所有Bean节点

            List<Element> beans = xsub.selectNodes(document);

            for (Element element : beans) {

                //获取id属性值

                String id = element.attributeValue("id");

                //获取class属性值

                String clazz = element.attributeValue("class");

                BeanDefinition beanDefinition = new BeanDefinition(id, clazz);

                //创建bean/property查询路径

                XPath propertysub = element.createXPath("ns:property");

                //设置命名空间

                propertysub.setNamespaceURIs(nsMap);

                //获取beanproperty列表节点

                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);

                    System.out.println(property);

                    //property属性添加到beanDefinition

                    beanDefinition.getProperties().add(propertyDefinition);

                }

                //将新创建的BeanDefinition赌侠ing放入到BeanDeifnitions

                beanDefines.add(beanDefinition);

            }

        } catch (Exception e) {

            System.out.println(e.toString());

        }

    }

 

    /**

     * 实例化bean,存入到sigletons

     */

    private void instanceBeans() {

        for (BeanDefinition beanDefinition : beanDefines) {

            try {

                if (beanDefinition.getClassName() != null

                    && !(beanDefinition.getClassName().isEmpty())) {

                    //利用java反射机制,生成BeanDefinition实例,并将其注册到sigletons

                    sigletons.put(beanDefinition.getId(), Class.forName(

                        beanDefinition.getClassName()).newInstance());

                }

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

 

    }

 

    /**

     * 根据ID名获取实例bean

     * return 返回一个Object对象,用户使用时,需要对获取的结果进行转换类型

     */

    public Object getBean(String beanName) {

        return this.sigletons.get(beanName);

    }

}

  

5 进行测试:

public class MyTest {

 

    public static void main(String[] args) {

        //MyIOC容器实例化

        WxyClassPathXMLApplicationContext ac = new WxyClassPathXMLApplicationContext("beans.xml");

        PeopleService peopleService = (PeopleService) ac.getBean("peopleService");

        peopleService.save();

    }

 

}

  

6 测试结果:

--> the method is called save()! name=wxy,id=218

this is the method PeopleDaoBean.add()!

  

 

 

 

文章评论

每天工作4小时的程序员
每天工作4小时的程序员
编程语言是女人
编程语言是女人
中美印日四国程序员比较
中美印日四国程序员比较
总结2014中国互联网十大段子
总结2014中国互联网十大段子
漫画:程序员的工作
漫画:程序员的工作
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
Java程序员必看电影
Java程序员必看电影
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
程序员都该阅读的书
程序员都该阅读的书
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
老程序员的下场
老程序员的下场
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
旅行,写作,编程
旅行,写作,编程
我是如何打败拖延症的
我是如何打败拖延症的
那些争议最大的编程观点
那些争议最大的编程观点
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
我的丈夫是个程序员
我的丈夫是个程序员
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
程序员必看的十大电影
程序员必看的十大电影
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
 程序员的样子
程序员的样子
为什么程序员都是夜猫子
为什么程序员都是夜猫子
10个调试和排错的小建议
10个调试和排错的小建议
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
程序员的鄙视链
程序员的鄙视链
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
如何成为一名黑客
如何成为一名黑客
程序员应该关注的一些事儿
程序员应该关注的一些事儿
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
程序员和编码员之间的区别
程序员和编码员之间的区别
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
代码女神横空出世
代码女神横空出世
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有