Small Spring系列一:BeanFactory(一)
人生如逆旅,我亦是行人。

前言
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.xml的bean的定义,下面我们使用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.xml,BeanDefinition来描述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 ");
    }
}
代码下载
类图

Small Spring系列一:BeanFactory(一)的更多相关文章
- 转:Spring系列之beanFactory与ApplicationContext
		原文地址:Spring系列之beanFactory与ApplicationContext 一.BeanFactoryBeanFactory 是 Spring 的“心脏”.它就是 Spring IoC ... 
- Spring系列之beanFactory与ApplicationContext
		一.BeanFactoryBeanFactory 是 Spring 的“心脏”.它就是 Spring IoC 容器的真面目.Spring 使用 BeanFactory 来实例化.配置和管理 Bean. ... 
- 深入理解Spring系列之三:BeanFactory解析
		转载 https://mp.weixin.qq.com/s?__biz=MzI0NjUxNTY5Nw==&mid=2247483824&idx=1&sn=9b7c2603093 ... 
- Spring 系列: Spring 框架简介 -7个部分
		Spring 系列: Spring 框架简介 Spring AOP 和 IOC 容器入门 在这由三部分组成的介绍 Spring 框架的系列文章的第一期中,将开始学习如何用 Spring 技术构建轻量级 ... 
- Spring 系列: Spring 框架简介(转载)
		Spring 系列: Spring 框架简介 http://www.ibm.com/developerworks/cn/java/wa-spring1/ Spring AOP 和 IOC 容器入门 在 ... 
- 通俗化理解Spring3 IoC的原理和主要组件(spring系列知识二总结)
		♣什么是IoC? ♣通俗化理解IoC原理 ♣IoC好处 ♣工厂模式 ♣IoC的主要组件 ♣IoC的应用实例 ♣附:实例代码 1.什么是IoC(控制反转)? Spring3框架的核心是实现控制反转(Io ... 
- 狗鱼IT教程:推介最强最全的Spring系列教程
		Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建. 简单来说,Spring是一个分层的JavaSE/EEfull-stack( ... 
- Spring系列之IOC的原理及手动实现
		目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 导语 Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架.也是几乎所有J ... 
- Spring系列之DI的原理及手动实现
		目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 前言 在上一章中,我们介绍和简单实现了容器的部分功能,但是这里还留下了很多的问题.比如我们在构造bean实例的时 ... 
- Spring系列之AOP的原理及手动实现
		目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 引入 到目前为止,我们已经完成了简易的IOC和DI的功能,虽然相比如Spring来说肯定是非常简陋的,但是毕竟我 ... 
随机推荐
- Tomcat源码分析 (四)----- Pipeline和Valve
			在 Tomcat源码分析 (二)----- Tomcat整体架构及组件 中我们简单分析了一下Pipeline和Valve,并给出了整体的结构图.而这一节,我们将详细分析Tomcat里面的源码. Val ... 
- vue过滤器微信小程序过滤器和百度智能小程序过滤器
			因为最近写了微信小程序和百度小程序,用到了过滤器,感觉还挺好用的,所以就来总结一下,希望能帮到你们. 1. 微信小程序过滤器: 1.1:首先建一个单独的wxs后缀的文件,一般放在utils文件夹里面. ... 
- 世纪龙校招java开发一、二面 面经
			头一天做的笔试,涉及到计组基本知识,还有几道智力题.java部分很简单(真的很简单有点基础就划过了) 第二天收简历 在隔壁教室等 叫到你 你就去面试 一面:先自我介绍 1 == 和 equals区别( ... 
- 【记忆化搜索】掷骰子 hpuoj
			B. 掷骰子 单点时限: 2.0 sec 内存限制: 512 MB 骰子,中国传统民间娱乐用来投掷的博具,早在战国时期就已经被发明. 现在给你 n 个骰子,求 n 个骰子掷出点数之和为 a 的概率是多 ... 
- java 判断 string 转 integer 判断
			NumberUtils.isDigits("1") NumberUtils.isDigits("/") 根据返回 true false 再确定是否转换即可 需要 ... 
- 打包一沓开源的 C/C++ 包管理工具送给你!
			本文作者:HelloGitHub-ChungZH 博客地址:https://chungzh.cn/ 包管理器可以帮助你更方便地安装依赖关系,并决定所安装的版本,提高你的开发幸福感.许多语言都有自己的包 ... 
- 【在 Nervos CKB 上做开发】Nervos CKB 脚本编程简介[1]:验证模型
			CKB 脚本编程简介[1]: 验证模型 本文作者:Xuejie 原文链接:Introduction to CKB Script Programming 1: Validation Model 本文译者 ... 
- 常用Http status code 如何记
			一直记不住http常用的status code,最近思考可以这样想.http无非就是客户端和服务端之间请求嘛.结果么要么成功,要么失败. 成功了,可以提示信息 -- Informational 1xx ... 
- jvm系列(四):jvm调优-命令篇
			运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎鼎的VisualVM,IBM的Memory Analyzer ... 
- 根据图中的盲点坐标,弹出div层
			<div class="map_r" id="mapinfo" style="position: absolute; top: 20px; le ... 
