zoukankan      html  css  js  c++  java
  • 模拟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);
                    }
                    
                }
        }
        
    }
    }
    }
    
    
    
    
    
    	
    	
    	
    

      

  • 相关阅读:
    微信聊天框测试思路
    巧用&&和|| 让逻辑代码更简洁,逼格看起来更高一点(玩笑脸)
    获取URL中的参数
    解决移动端点击闪烁问题
    npm安装依赖包 --save-dev 和 --save; package.json的devDependencies和dependencies 的区别!
    vue-cli 3配置接口代理
    js小方法积累,将一个数组按照n个一份,分成若干数组
    web前端识别文字转语音
    html 锚点
    ES6 必须要用的数组Filter() 方法,不要再自己循环遍历了!!!
  • 原文地址:https://www.cnblogs.com/xiohao/p/4391541.html
Copyright © 2011-2022 走看看