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

前言

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

代码下载

类图

Small Spring系列一:BeanFactory(一)的更多相关文章

  1. 转:Spring系列之beanFactory与ApplicationContext

    原文地址:Spring系列之beanFactory与ApplicationContext 一.BeanFactoryBeanFactory 是 Spring 的“心脏”.它就是 Spring IoC ...

  2. Spring系列之beanFactory与ApplicationContext

    一.BeanFactoryBeanFactory 是 Spring 的“心脏”.它就是 Spring IoC 容器的真面目.Spring 使用 BeanFactory 来实例化.配置和管理 Bean. ...

  3. 深入理解Spring系列之三:BeanFactory解析

    转载 https://mp.weixin.qq.com/s?__biz=MzI0NjUxNTY5Nw==&mid=2247483824&idx=1&sn=9b7c2603093 ...

  4. Spring 系列: Spring 框架简介 -7个部分

    Spring 系列: Spring 框架简介 Spring AOP 和 IOC 容器入门 在这由三部分组成的介绍 Spring 框架的系列文章的第一期中,将开始学习如何用 Spring 技术构建轻量级 ...

  5. Spring 系列: Spring 框架简介(转载)

    Spring 系列: Spring 框架简介 http://www.ibm.com/developerworks/cn/java/wa-spring1/ Spring AOP 和 IOC 容器入门 在 ...

  6. 通俗化理解Spring3 IoC的原理和主要组件(spring系列知识二总结)

    ♣什么是IoC? ♣通俗化理解IoC原理 ♣IoC好处 ♣工厂模式 ♣IoC的主要组件 ♣IoC的应用实例 ♣附:实例代码 1.什么是IoC(控制反转)? Spring3框架的核心是实现控制反转(Io ...

  7. 狗鱼IT教程:推介最强最全的Spring系列教程

    Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建. 简单来说,Spring是一个分层的JavaSE/EEfull-stack( ...

  8. Spring系列之IOC的原理及手动实现

    目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 导语 Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架.也是几乎所有J ...

  9. Spring系列之DI的原理及手动实现

    目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 前言 在上一章中,我们介绍和简单实现了容器的部分功能,但是这里还留下了很多的问题.比如我们在构造bean实例的时 ...

  10. Spring系列之AOP的原理及手动实现

    目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 引入 到目前为止,我们已经完成了简易的IOC和DI的功能,虽然相比如Spring来说肯定是非常简陋的,但是毕竟我 ...

随机推荐

  1. 原生JavaScript(js)手把手教你写轮播图插件(banner)

    ---恢复内容开始--- 1.轮播图插件 1.什么是插件: 为已有的程序增加功能 2.插件的特点(为什么要做成一个插件)与注意事项: 1.通用性,可移植性强 2.兼容性:不会对其他代码产生影响 3.创 ...

  2. dart的基本语法(一)

    Hello world ​ 安装dart的环境就不赘述了,无脑安装就可以了,安装过程中好像需要梯子(vpn),我装的时候失败好多次,我的梯子不能用了,准备不装了的时候,莫名其妙的装好了.迷の操作.惯例 ...

  3. js动态添加<tr><td>

    <form id="addNewsFormData" name="addNewsFormData" isCheck="true" ac ...

  4. 【win10主机】访问virtualbox上【32位winXP系统虚拟机】上启动的项目

    win10上创建虚拟网卡: 1,右键此电脑点击管理——设备管理器——网络适配器: 2,点左上角菜单栏的 操作——添加过时硬件: 3,点下一步 4,点安装我手动从列表选择的硬件(高级)M 5,点网络适配 ...

  5. ansible批量自动配置Juniper

    一.需求 有几台新上线的Juniper,需要批量配置下syslog,ntp,snmp基础配置 二.拓扑 三.实施步骤 1.读取配置并输出作为初步核查 2.把配置载入网络其中一台网络设备中,并做一个sh ...

  6. 并发编程 Semaphore的使用和详解

    类Semaphore的基本使用 Semaphore的作用:限制线程并发的数量 课外话题[多线程的同步概念]:其实就是排着队去执行一个任务,执行任务是一个一个的执行,这样的优点是有助于程序逻辑的正确性, ...

  7. net core 3.0 之Grpc新特性小试牛刀

      相信微服务大家伙都有听说和知道,好处弊端咱也不多说了,Grpc算是一个比较全面的微服务框架,也得到微软的支持 总结下来就是,跨平台,可靠,通信快,扩展性强,网络消耗小,模板多语言通用 光说好处,没 ...

  8. 从 Python 之父的对话聊起,关于知识产权、知识共享与文章翻译

    一.缘起 前不久,我在翻译 Guido van Rossum(Python之父)的文章时,给他留言,申请非商业用途的翻译授权. 过程中起了点小误会,略去不表,最终的结果是:他的文章以CC BY-NC- ...

  9. Springboot + Stopping service [Tomcat]+ Process finished with exit code 0

    在Springboot 的版本为: <version>1.5.10.RELEASE</version> 原因:代码中有非法格式的结构,及代码写错啦,例如: <result ...

  10. Java8中Instant和LocalDate来计算时间或者日期间隔

    /** * java.time.Instant * java.time.Duration * Instant 默认使用UTC时区:2019-01-24T14:01:32.258Z * mongo中的时 ...