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 "); } }
代码下载
类图
相关推荐
与卿画眉共浮生 2020-10-14
tangxiong0 2020-09-03
YangHuiLiang 2020-08-06
smalllove 2020-07-27
MicroBoy 2020-07-04
爱莲说 2020-06-26
itjavashuai 2020-06-25
杜鲁门 2020-11-05
lukezhong 2020-10-14
Sweetdream 2020-08-03
编程点滴 2020-07-29
iconhot 2020-07-05
XGQ 2020-07-04
itjavashuai 2020-07-04
zmysna 2020-07-04
willluckysmile 2020-06-29
CoderBoy 2020-06-28
HappyHeng 2020-06-21
smalllove 2020-06-14