前导:开始学习Spring核心思想,通过一个山寨精简版Spring代码结合学习。
内容:1. BeanDefinitionReader-配置读取者。 2. XmlBeanDefinitionReader-从XML中读取配置。 3. Resource-定位资源文件。这次将Bean的配置信息都放到了XML里,所以这里会有一个XML文件的读取,我们通过XmlBeanDefinitionReader将XML中的信息组装好成BeanDefinition放到一个Map里,这样我们就能真正做到像Spring那样靠配置文件来组装Bean。
重复的代码不再列出
BeanDefinition:
public class BeanDefinition { private Object bean; private Class beanClass; private String beanClassName; private PropertyValues propertyValues = new PropertyValues(); public BeanDefinition() {} public Object getBean() { return bean; } public void setBean(Object bean) { this.bean = bean; } public Class getBeanClass() { return beanClass; } public void setBeanClass(Class beanClass) { this.beanClass = beanClass; } public String getBeanClassName() { return beanClassName; } public void setBeanClassName(String beanClassName) { this.beanClassName = beanClassName; try { this.beanClass = Class.forName(beanClassName); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public PropertyValues getPropertyValues() { return propertyValues; } public void setPropertyValues(PropertyValues propertyValues) { this.propertyValues = propertyValues; } }
Resource:
/** * Resource是spring内部定位资源接口 * @author acer */ public interface Resource { InputStream getInputStream() throws IOException; }
ResourceLoader:
public class ResourceLoader { public Resource getResource(String location) { URL resource = this.getClass().getClassLoader().getResource(location); return new UrlResource(resource); } }
UrlResource:
public class UrlResource implements Resource{ private final URL url; public UrlResource(URL url) { this.url = url; } @Override public InputStream getInputStream() throws IOException { URLConnection urlConnection = url.openConnection(); urlConnection.connect(); return urlConnection.getInputStream(); } }
BeanDefinitionReader:
/** * 从配置中读取BeanDefinitionReader * @author acer * */ public interface BeanDefinitionReader { void loadBeanDefinitions(String location) throws Exception; }
AbstractBeanDefinitionReader:
/** * 从配置中读取BeanDefinitionReader * @author acer * */ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader{ private Map<String, BeanDefinition> registry; private ResourceLoader resourceLoader; protected AbstractBeanDefinitionReader(ResourceLoader resourceLoader) { this.registry = new HashMap<String, BeanDefinition>(); this.resourceLoader = resourceLoader; } public Map<String, BeanDefinition> getRegistry() { return this.registry; } public ResourceLoader getResourceLoader() { return resourceLoader; } }
XmlBeanDefinitionReader:
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader{ public XmlBeanDefinitionReader(ResourceLoader resourceLoader) { super(resourceLoader); } @Override public void loadBeanDefinitions(String location) throws Exception { InputStream inputStream = getResourceLoader().getResource(location).getInputStream(); doLoadBeanDefinitions(inputStream); } protected void doLoadBeanDefinitions(InputStream inputStream) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = factory.newDocumentBuilder(); Document doc = docBuilder.parse(inputStream); //解析bean registerBeanDefinitions(doc); inputStream.close(); } public void registerBeanDefinitions(Document doc) { Element root = doc.getDocumentElement(); parseBeanDefinitions(root); } protected void parseBeanDefinitions(Element root) { NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; processBeanDefinition(ele); } } } protected void processBeanDefinition(Element ele) { String name = ele.getAttribute("name"); String className = ele.getAttribute("class"); BeanDefinition beanDefinition = new BeanDefinition(); processProperty(ele, beanDefinition); beanDefinition.setBeanClassName(className); getRegistry().put(name, beanDefinition); } private void processProperty(Element ele, BeanDefinition beanDefinition) { NodeList propertyNode = ele.getElementsByTagName("property"); for (int i = 0; i < propertyNode.getLength(); i++) { Node node = propertyNode.item(i); if (node instanceof Element) { Element propertyEle = (Element) node; String name = propertyEle.getAttribute("name"); String value = propertyEle.getAttribute("value"); beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, value)); } } } }
public class BeanFactoryTest { @Test public void test() throws Exception{ // 1.读取配置 XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader()); xmlBeanDefinitionReader.loadBeanDefinitions("tinyioc.xml"); // 2.初始化BeanFactory并注册bean BeanFactory beanFactory = new AutowireCapableBeanFactory(); for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue()); // 3. 获取bean HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService"); helloWorldService.helloWorld(); } }
tinyioc.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <bean name="helloWorldService" class="step4.test.HelloWorldService"> <property name="text" value="Hello World! from step4!"></property> </bean> </beans>
时间: 2024-10-12 17:34:08