人生如逆旅,我亦是行人。php
Spring是一個開放源代碼的設計層面框架,它解決的是業務邏輯層和其餘各層的鬆耦合問題,所以它將面向接口的編程思想貫穿整個系統應用。java
bean-v1.xml
配置bean
的信息BeanDefinition
用於存放bean
的定義BeanFactory
獲取bean的信息,實例化
bean`BeanFactoryTest
測試BeanFactory
是否可用<?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>
複製代碼
bean-v1.xml
中定義了每一個bean
,但這些信息咱們該如何存儲呢? spring
是經過BeanDefinition
接口來描述bean
的定義git
package com.niocoder.beans;
/** * bean.xml bean的定義 * @author zhenglongfei */
public interface BeanDefinition {
/** * 獲取bean.xml中 bean的全名 如 "com.niocoder.service.v1.NioCoderService" * @return */
String getBeanClassName();
}
複製代碼
GenericBeanDefinition
實現了BeanDefinition
接口github
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;
}
}
複製代碼
咱們已經使用BeanDefinition
來描述bean-v1.xml
的bean
的定義,下面咱們使用BeanFactory
來獲取bean
的實例spring
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
實現了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");
}
}
}
複製代碼
以上,咱們已經建立了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 ");
}
}
複製代碼