模拟Spring中applicationContext.xml配置文件初始化bean的过程

package com.xiaohao.action;

import java.io.File;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

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

/**
 * 需要导入dom4j的jar包
 * @author 小浩
 * @创建日期 2015-4-4
 */
public class BeanFactory {

	/**
     * 保存容器中所有单例模式的bean实例,这里的hashMap是线程安全的
     *
     */

	private static Map<String,Object> beanPool=Collections.synchronizedMap(new HashMap<String,Object>());
    //保存文件对应的Document对象
    private Document document;
    //保存配置文件里的根元素
    private Element root;

    /**
     * 构造方法,指定需要读取的文件的路径
     * @param filePath
     * @throws Exception
     */
    public BeanFactory(String filePath) throws Exception{

    	//使用dom4j读取xml配置文件
    	SAXReader reader=new SAXReader();
        document=reader.read(new File(filePath));
    	root=document.getRootElement();
    	 //进行容器的初始化
        initPool();
        //初始化单例bean的属性
        initProp();

      }

    /**
     * 获取指定的bean
     * @param name
     * @return
     * @throws Exception
     */
	public static Object getBean(String name) throws Exception {
    	Object target = beanPool.get(name);
        //对于单例bean,容器已经初始化了所有的Bean实例
        if(target.getClass() != String.class){
            return target;
        }else{
            String clazz = (String)target;
            //对于非单例的并未注入属性值
            return Class.forName(clazz).newInstance();
        }

	}

    /**
     * 初始化容器中的所有单例bean
     * */
    private void initPool() throws Exception{
        //遍历配置文件中的每个<bean ../>元素
        for(Object obj:root.elements()){
            Element beanElement = (Element)obj;
            //获取Bean元素中的id属性
            String beanId = beanElement.attributeValue("id");
            //获取bean元素中的class属性
            String beanClazz = beanElement.attributeValue("class");
            //获取bean元素中的scope属性
            String beanScope = beanElement.attributeValue("scope");
            //如果scope属性不存在或为singleton
            if(beanScope == null|| beanScope.equals("singleton")){
                //以默认构造方法创建bean实例,并将其放入beanPool中
                beanPool.put(beanId, Class.forName(beanClazz).newInstance());   //利用反射的技术
            }else{
                //对于非单例的,存放Bean实现类的类名
               beanPool.put(beanId, beanClazz);
            }
        }

    }

/**
 * 初始化容器中的单例bean
 * */
private void initProp() throws Exception{
    //遍历配置文件中的所有bean元素,即根节点的子节点
    for(Object object:root.elements()){
        Element beanElement = (Element)object;
        //获取Bean元素中的id属性
        String beanId = beanElement.attributeValue("id");
        //获取bean元素中的scope属性
        String beanScope = beanElement.attributeValue("scope");
        //如果scope属性不存在或为singleton
        if(beanScope == null|| beanScope.equals("singleton")){
            //取出beanPool的指定bean实例
            Object bean = beanPool.get(beanId);
            //遍历bean属性下的所有property属性
            for(Object prop: beanElement.elements()){
                Element probElement = (Element)prop;
                //获取property的name属性
                String propName = probElement.attributeValue("name");
                //获取property的value属性
                String propValue = probElement.attributeValue("value");
                //获取property的ref属性
                String propRef = probElement.attributeValue("ref");
                //将属性名的首字母大写
                String propNameCamelize = propName.substring(0,1).toUpperCase()
                    +propName.substring(1, propName.length());
                //如果value值存在
                if(propValue != null&&propValue.length()> 0){
                    //获取设置注入所需要的setter方法
                    java.lang.reflect.Method setter = bean.getClass().getMethod("set"+propNameCamelize, String.class);
                    //执行setter注入
                    setter.invoke(bean, propValue);
                }
                if(propRef != null&&propRef.length()> 0){
                    //取得需要被注入的bean实例
                    Object target = beanPool.get(propRef);
                    //如果不存在
                    if(target == null){
                        //此处处理单例bean依赖于非单例bean的情形
                    }
                    //定义设值注入需要的setter方法
                    Method setter = null;
                    //遍历target对象所实现的所有方法
                    for(Class superInterface: target.getClass().getInterfaces()){
                        try{
                            //获取设置注入所需要的setter方法
                            setter = bean.getClass().getMethod("set"+propNameCamelize, superInterface);
                            //如果成功获取,跳出循环
                            break;
                        }catch (Exception e) {
                            //如果没有找到就继续下次循环
                            continue;
                        }
                    }
                    //如果setter方法依然是null,直接取得target的实现类对应的setter方法
                    if(setter == null){
                        setter = bean.getClass().getMethod("set"+propNameCamelize, target.getClass());
                    }
                    //执行setter注入
                    setter.invoke(bean, target);
                }

            }
    }

}
}
}

  

时间: 2024-12-15 01:57:16

模拟Spring中applicationContext.xml配置文件初始化bean的过程的相关文章

关于spring的applicationContext.xml配置文件的ref和value之自我想法

今天在做SSH的一个项目的时候,因为需要定时操作,所以就再sping里面加入了一个quartz的小定时框架,结果在运行时候,发生了一个小bug. Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.String' to required type 'org.quartz.spi.JobFactory' fo

SSM:spring+springmvc+mybatis框架中的XML配置文件功能详细解释

SSM:spring+springmvc+mybatis框架中的XML配置文件功能详细解释 2016-04-14 23:40 13030人阅读 评论(2) 收藏 举报 分类: SSM(7) 这几天一直在整合SSM框架,虽然网上有很多已经整合好的,但是对于里面的配置文件并没有进行过多的说明,很多人知其然不知其所以然,经过几天的搜索和整理,今天总算对其中的XML配置文件有了一定的了解,所以拿出来一起分享一下,希望有不足的地方大家批评指正~~~ 首先   这篇文章暂时只对框架中所要用到的配置文件进行解

跟着刚哥学习Spring框架--通过XML方式配置Bean(三)

Spring配置Bean有两种形式(XML和注解) 今天我们学习通过XML方式配置Bean 1. Bean的配置方式 通过全类名(反射)的方式   √ id:标识容器中的bean.id唯一. √ class:bean的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须有无参的构造器 2.依赖注入的方式 1)属性注入:通过setter方法注入Bean的属性值或依赖的对象 属性注入使用<Property>元素,使用name指定Bean的属性名称,使用value指定Bean的属

Spring中&lt;ref local=&quot;&quot;/&gt;与&lt;ref bean=&quot;&quot;/&gt;区别

小 Spring中<ref local=""/>与<ref bean=""/>区别 (2011-03-19 19:21:58) 转载▼ 标签: 杂谈   <ref local="xx"/>  用"local"属性指定目标其实是指向同一文件内对应"id"属性值为此"local"值的索引"local"属性的值必须和目标bean的id属性

Spring 框架的概述以及Spring中基于XML的IOC配置

Spring 框架的概述以及Spring中基于XML的IOC配置 一.简介 Spring的两大核心:IOC(DI)与AOP,IOC是反转控制,DI依赖注入 特点:轻量级.依赖注入.面向切面编程.容器.框架.一站式 优势: 方便解耦:做到编译期不依赖,运行期才依赖 AOP的支持 声明式事务的支持 方便程序的测试 方便整合各种框架 降低JavaEE API的使用难度 Spring源码很厉害 解耦: 耦合包括:类之间的和方法之间的 解决的思路: 在创建对象的时候用反射来创建,而不是new 读取配置文件

Spring中引入其他配置文件

一.引入其他 模块XML 在Spring的配置文件,有时候为了分模块的更加清晰的进行相关实体类的配置. 比如现在有一个job-timer.xml的配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XML

Spring中ApplicationContext对事件的支持

Spring中ApplicationContext对事件的支持 ApplicationContext具有发布事件的能力.这是因为该接口继承了ApplicationEventPublisher接口.Spring中与事件有关的接口和类主要包括ApplicationEvent.ApplicationListener.定义一个事件的类需要继承ApplicationEvent或者ApplicationContextEvent抽象类,该抽象类中只有一个构造函数,并 且带有一个Object类型的参数作为事件源

Spring中自动检测并申明bean

在Spring中申明bean,一般情况是在XML中用<bean id=""  class="">标签来指定一个类并为其取一个id.但是这样效率很低,Spring提供了自动检测并申明bean的方法,讲解如下: 一.自动检测并申明bean的步骤: 1.用<context:component-scan  base-package="com.springinaction.springidol"></context:compo

Struts2框架中书写XML配置文件时能添加提示技巧(方案二)

1.  先在/工程名/WebRoot/WEB-INF/lib/struts2-core-2.1.8.jar中找到struts-2.1.dtd文件. 2.  在Myeclipse8.6-->Window-->Preferences 3.  在搜索框输入xml文件,找到XMLCatalog,单击XML Catalog出现如上页面,之后单击Add按钮,出现如下图: 4.  在Location中选择FileSystem,选择struts-2.1.dtd文件的位置,如果这个文件在工程里面,可以使用Wor