zoukankan      html  css  js  c++  java
  • Small Spring系列一:BeanFactory(一)

    人生如逆旅,我亦是行人。

    https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/spring/small-spring-01.jpg

    前言

    Spring是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。

    准备

    • bean-v1.xml配置bean的信息
    • BeanDefinition用于存放bean的定义
    • BeanFactory获取bean的信息,实例化bean`
    • BeanFactoryTest测试BeanFactory是否可用

    bean-v1.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
        <bean id = "nioCoder"
            class = "com.niocoder.service.v1.NioCoderService">
        </bean>
    
        <bean id ="invalidBean"
            class="xxx.xxx">
        </bean>
    </beans>
    

    BeanDefinition

    bean-v1.xml中定义了每个bean,但这些信息我们该如何存储呢?
    spring是通过BeanDefinition接口来描述bean的定义

    BeanDefinition

    package com.niocoder.beans;
    
    /**
     * bean.xml bean的定义
     * @author zhenglongfei
     */
    public interface BeanDefinition {
    
        /**
         * 获取bean.xml中 bean的全名 如 "com.niocoder.service.v1.NioCoderService"
         * @return
         */
        String getBeanClassName();
    }
    
    

    GenericBeanDefinition

    GenericBeanDefinition实现了BeanDefinition接口

    package com.niocoder.beans.factory.support;
    
    
    import com.niocoder.beans.BeanDefinition;
    
    /**
     * BeanDefinition 实现类
     *
     * @author zhenglongfei
     */
    public class GenericBeanDefinition implements BeanDefinition {
    
        private String id;
        private String beanClassName;
    
        public GenericBeanDefinition(String id, String beanClassName) {
            this.id = id;
            this.beanClassName = beanClassName;
        }
    
        public String getBeanClassName() {
            return this.beanClassName;
        }
    }
    
    
    

    BeanFactory

    我们已经使用BeanDefinition来描述bean-v1.xmlbean的定义,下面我们使用BeanFactory来获取bean的实例

    BeanFactory

    package com.niocoder.beans.factory;
    
    import com.niocoder.beans.BeanDefinition;
    
    /**
     * 创建bean的实例
     * @author zhenglongfei
     */
    public interface BeanFactory {
    
        /**
         * 获取bean的定义
         * @param beanId
         * @return
         */
        BeanDefinition getBeanDefinition(String beanId);
    
        /**
         * 获取bean的实例
         * @param beanId
         * @return
         */
        Object getBean(String beanId);
    }
    
    

    DefaultBeanFactory

    DefaultBeanFactory实现了BeanFactory接口

    package com.niocoder.beans.factory.support;
    
    import com.niocoder.beans.BeanDefinition;
    import com.niocoder.beans.factory.BeanCreationException;
    import com.niocoder.beans.factory.BeanDefinitionStoreException;
    import com.niocoder.beans.factory.BeanFactory;
    import com.niocoder.util.ClassUtils;
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    import java.io.InputStream;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    
    /**
     * BeanFactory的默认实现类
     *
     * @author zhenglongfei
     */
    public class DefaultBeanFactory implements BeanFactory {
    
        private static final String ID_ATTRIBUTE = "id";
    
        private static final String CLASS_ATTRIBUTE = "class";
        /**
         * 存放BeanDefinition
         */
        private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    
        /**
         * 根据文件名称加载,解析bean.xml
         *
         * @param configFile
         */
        public DefaultBeanFactory(String configFile) {
            loadBeanDefinition(configFile);
        }
    
        /**
         * 具体解析bean.xml的方法 使用dom4j
         *
         * @param configFile
         */
        private void loadBeanDefinition(String configFile) {
            ClassLoader cl = ClassUtils.getDefaultClassLoader();
            try (InputStream is = cl.getResourceAsStream(configFile)) {
                SAXReader reader = new SAXReader();
                Document doc = reader.read(is);
    
                Element root = doc.getRootElement();
                Iterator<Element> elementIterator = root.elementIterator();
                while (elementIterator.hasNext()) {
                    Element ele = elementIterator.next();
                    String id = ele.attributeValue(ID_ATTRIBUTE);
                    String beanClassName = ele.attributeValue(CLASS_ATTRIBUTE);
                    BeanDefinition bd = new GenericBeanDefinition(id, beanClassName);
                    this.beanDefinitionMap.put(id, bd);
                }
            } catch (Exception e) {
                throw new BeanDefinitionStoreException("IOException parsing XML document", e);
            }
        }
    
        @Override
        public BeanDefinition getBeanDefinition(String beanId) {
            return this.beanDefinitionMap.get(beanId);
        }
    
        @Override
        public Object getBean(String beanId) {
            BeanDefinition bd = this.getBeanDefinition(beanId);
            if (bd == null) {
                throw new BeanCreationException("BeanDefinition does not exist");
            }
            ClassLoader cl = ClassUtils.getDefaultClassLoader();
    
            String beanClassName = bd.getBeanClassName();
            try {
                // 使用反射创建bean的实例,需要对象存在默认的无参构造方法
                Class<?> clz = cl.loadClass(beanClassName);
                return clz.newInstance();
            } catch (Exception e) {
                throw new BeanCreationException("Bean Definition does not exist");
            }
        }
    }
    
    

    BeanFactoryTest

    以上,我们已经创建了bean.xmlBeanDefinition来描述bean的定义,并且使用BeanFactory来获取bean的实例。下面我们来测试一下BeanFactory是否可用。

    package com.niocoder.test.v1;
    
    import com.niocoder.beans.BeanDefinition;
    import com.niocoder.beans.factory.BeanCreationException;
    import com.niocoder.beans.factory.BeanDefinitionStoreException;
    import com.niocoder.beans.factory.BeanFactory;
    import com.niocoder.beans.factory.support.DefaultBeanFactory;
    import com.niocoder.service.v1.NioCoderService;
    import org.junit.Assert;
    import org.junit.Test;
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertNotNull;
    
    /**
     * BeanFactory 测试类
     */
    public class BeanFactoryTest {
    
        /**
         * 测试获取bean
         */
        @Test
        public void testGetBean() {
            BeanFactory factory = new DefaultBeanFactory("bean-v1.xml");
            BeanDefinition bd = factory.getBeanDefinition("nioCoder");
    
            assertEquals("com.niocoder.service.v1.NioCoderService", bd.getBeanClassName());
    
            NioCoderService nioCoderService = (NioCoderService) factory.getBean("nioCoder");
    
            assertNotNull(nioCoderService);
        }
    
        /**
         * 测试无效的bean
         */
        @Test
        public void testInvalidBean() {
            BeanFactory factory = new DefaultBeanFactory("bean-v1.xml");
            try {
                factory.getBean("invalidBean");
            } catch (BeanCreationException e) {
                return;
            }
    
            Assert.fail("expect BeanCreationException ");
        }
    
        /**
         * 测试无效的xml
         */
        @Test
        public void testInvalidXML() {
            try {
                new DefaultBeanFactory("xxx.xml");
            } catch (BeanDefinitionStoreException e) {
                return;
            }
    
            Assert.fail("expect BeanDefinitionStoreException ");
        }
    }
    
    

    代码下载

    类图

    https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/spring/beanfactory_v1.png

  • 相关阅读:
    关于ubantu在VMWARE里安装时出现'SMBus Host Controller not enabled'
    临时备忘录
    第七届 山东ACM热身赛 Dwarf Tower
    数学问题题目连接
    蓝桥杯2016决赛 凑平方数
    博弈整理(取物)
    格子刷油漆(DP)
    蓝桥杯第六届总决赛B组
    蓝桥杯第五届决赛B组
    蓝桥杯第四届总决赛
  • 原文地址:https://www.cnblogs.com/merryyou/p/10267023.html
Copyright © 2011-2022 走看看