身为java程序员,spring 或多或少的接触,但是我们经常从spring这个大容器里获取的bean到底是怎么获取的呢?小编给你分析一波
首先定义一个BeanFactory,模拟spring的工厂
package com.dingjianlei.spring.ioc;
public interface BeanFactory {
public Object getBean(String id);
}
这是声明了一个BeanFactory,模拟一下spring的bean工厂(ps:当然spring那庞大的spi需要读者自己理清。。。)
定义 ClassPathApplicationContext 模拟spring的 ClassPathXmlApplicationContext 继承BeanFactory, ClassPathApplicationContext 这个类里面自定义读取xml配置文件的代码
package com.dingjianlei.spring.ioc;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* 自定义beanFactory 获取自定义xml bean 放入ConcurrentHashMap,防止多线程进行读取
*
* @author 丁建磊
*
*/
public class ClassPathApplicationContext implements BeanFactory {
private ConcurrentHashMap<String, Object> beans = new ConcurrentHashMap<String, Object>();
private final String rootElementName = "bean";// 根节点
private Logger logger = LoggerFactory.getLogger(ClassPathApplicationContext.class);
public ClassPathApplicationContext() {
try {
// 1.创建解析工厂:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 2.指定DocumentBuilder
DocumentBuilder db = factory.newDocumentBuilder();
// 3.从文件构造一个Document,因为XML文件中已经指定了编码,所以这里不必了
ClassLoader classLoader = ClassPathApplicationContext.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("beans.xml");
Document doc = db.parse(resourceAsStream);
// 获取根节点
Element root = doc.getDocumentElement();
NodeList nodeList = root.getElementsByTagName(rootElementName);
if (nodeList != null) {
for (int i = 0; i < nodeList.getLength(); i++) {
if (nodeList.item(i).getNodeType() == Element.ELEMENT_NODE) {
Element item = (Element) nodeList.item(i);
String attribute = item.getAttribute("id");
String clazz = item.getAttribute("class");
Object o = Class.forName(clazz).newInstance();
beans.put(attribute, o);
}
}
}
} catch (Exception e) {
// TODO: handle exception
logger.info("解析配置文件错误");
}
}
public Object getBean(String id) {
// TODO Auto-generated method stub
return beans.get(id);
}
}
模拟读取spring的applicationContext.xml文件,里面需要的技术dom解析xml。
最后,定义一个测试类,运行一下我们的程序
package com.dingjianlei.spring.ioc;
import com.dingjianlei.service.DaoService;
public class IOC {
public static void main(String[] args) {
ClassPathApplicationContext context =new ClassPathApplicationContext();
DaoService daoService=(DaoService) context.getBean("stuDao");
daoService.getDao();
}
}