拿起笔来做刀枪 · 之二 再造一个spring

首先回顾一下我在前面章节提到的内容:

开发,从需求出发 · 之四 春天在这里

我们离spring的内容只有一步之遥,正如前文所说:

	private static Map<String, String> appBean = new HashMap<String, String>();
	private static Map<String, String[]> appRef = new HashMap<String, String[]>();
	
	static {
		appBean.put("luceneDAO", "cn.com.sitefromscrath.dao.LuceneDAOMock");
		appBean.put("mysqlDAO", "cn.com.sitefromscrath.dao.MysqlDAOMock");
		appBean.put("searchService", "cn.com.sitefromscrath.service.SearchServiceInRealBiz");
		
		appRef.put("searchService", new String[]{"luceneDAO", "mysqlDAO"});
	}

请比较和spring.xml的区别:

<?xml version="1.0" encoding="UTF-8"?>
<beans >

	<bean id="luceneDAO" class="cn.com.sitefromscrath.dao.LuceneDAOMock" />
	
	<bean id="mysqlDAO" class="cn.com.sitefromscrath.dao.MysqlDAOMock" /> 
	
	<bean id="searchService" class="cn.com.sitefromscrath.service.SearchServiceInRealBiz">
		<constructor-arg index="1" ref="luceneDAO" />
		<constructor-arg index="2" ref="mysqlDAO" />
	</bean>  

</beans>

好吧,没什么根本上的区别, 我们同样能够解析xml,得到我们自己实现的BeanFactory所需要的一切要素


由于有前一章的基础,我们只需要调用实现的 XmlParser进行整合就可以了:)


请遵守另一个原则,“不要想太多,从最简单的实现”入手。

我们其实需要的仅仅是一个 适配器,Adaptor。

让我们通过代码硬编码赋值进去的内容变成 首先解析xml,然后再赋值给:

	private static Map<String, String> appBean = new HashMap<String, String>();
	private static Map<String, String[]> appRef = new HashMap<String, String[]>();

由此,先得到方法:

	public static void fillAppInitParams(Node root){
		
		for(int i = 0; i < root.getChildren().size(); i++) {
			
			Node bean = (Node) root.getChildren().get(i);
			
			String id = bean.getAttributes().get("id");
			String clazz = bean.getAttributes().get("class");
			
			appBean.put(id, clazz);
			
			if(!bean.getChildren().isEmpty()) {
				
				List<String> refs = new ArrayList<String>();
				for(int k = 0; k < bean.getChildren().size(); k++) {
					Node arg = (Node)bean.getChildren().get(k);
					refs.add(arg.getAttributes().get("ref"));
				}
				
				appRef.put(id, refs.toArray(new String[0]));
			}
		}
	}

然后,读取xml,解析,然后将获得的根节点传入:

	public static void init() {
		try {
			XmlParser xmlParser = new XmlParser();
			InputStream is = xmlParser.getClass().getResourceAsStream("./test.xml");
			DomTree dt = xmlParser.build(is);
			is.close();			
			
			fillAppInitParams(dt.getRoot());
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

最后,我们和BeanFactory进行整合:


package net.csdn.blog.deltatang;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.csdn.blog.deltatang.dom4me.DomTree;
import net.csdn.blog.deltatang.dom4me.Node;
import net.csdn.blog.deltatang.dom4me.XmlParser;

public class BeanFactory {
	
	private static boolean initSucc = false;
	private static Map<String, String> appBean = new HashMap<String, String>();
	private static Map<String, String[]> appRef = new HashMap<String, String[]>();
	
	public static void fillAppInitParams(Node root){
		
		for(int i = 0; i < root.getChildren().size(); i++) {
			
			Node bean = (Node) root.getChildren().get(i);
			
			String id = bean.getAttributes().get("id");
			String clazz = bean.getAttributes().get("class");
			
			appBean.put(id, clazz);
			
			if(!bean.getChildren().isEmpty()) {
				
				List<String> refs = new ArrayList<String>();
				for(int k = 0; k < bean.getChildren().size(); k++) {
					Node arg = (Node)bean.getChildren().get(k);
					refs.add(arg.getAttributes().get("ref"));
				}
				
				appRef.put(id, refs.toArray(new String[0]));
			}
		}
	}
	
	public static void init() {
		try {
			XmlParser xmlParser = new XmlParser();
			InputStream is = xmlParser.getClass().getResourceAsStream("./test.xml");
			DomTree dt = xmlParser.build(is);
			is.close();			
			
			fillAppInitParams(dt.getRoot());
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
		
	public static Object getBean(String id) {
		
		if(initSucc) {
			init();
			initSucc = true;
		}
		
		try {
		
			String className = appBean.get(id);		
			Class clazz = Class.forName(className);
			Constructor constructor;
			
			String[] ref = appRef.get(id);
			
			if(ref == null || ref.length == 0) {			
				constructor = clazz.getConstructor();
				return (Object)constructor.newInstance();
			}
			
			Class[] parameterTypes = new Class[ref.length];
			Object[] initargs = new Object[ref.length];
			
			for(int i = 0; i < ref.length; i++) {
				String r = ref[i];
				
				String rclassName = appBean.get(r);
				parameterTypes[i] = Class.forName(rclassName).getInterfaces()[0]; //这里我偷懒了:)
				initargs[i] = getBean(r);
			}
			
			constructor = clazz.getConstructor(parameterTypes);
			
			return (Object)constructor.newInstance(initargs);
			
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}		
	}
	
	public static void main(String ... arg) {
		
		LuceneDAO luceneDAO = (LuceneDAO) getBean("luceneDAO");
		int[] vals = luceneDAO.findDocIDs("test");
		for(int v : vals) {
			System.out.println(v);
		}
		
		String keywords = "test";
		SearchService searchService = (SearchService)getBean("searchService");	
		List results = searchService.search(keywords);
		for(int i = 0; i < results.size(); i++) {
			Result result = (Result) results.get(i);
			System.out.print("[" + result.title + "]");
			System.out.println(result.content);
		}
	}

}

最终,我们得到了一个类似spring 的类装配和组织框架。

当然,它相当简陋,不过,足够我们阐述清楚问题,并在我们的项目sitefromscratch中使用。

如果继续向spring靠拢,比如,我们要实现 spring的

singlton="flase" lazy="true"

并不是一件很困难的工作,当然,我无意去“重复发明轮子”,我的目的是通过一个自己的实现去尝试理解成熟框架的实现机制和思想。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值