由于需要框架能实现多态,达到控制反转解耦。所以容器还是需要的,容器的存在可以简化对象获取工作,但是容器也不是万能的。合理使用即可,Spring对我来说太庞大了,用不着,为此给框架写一个迷你版容器。
容器配置还是继承以前用spring.net的容器配置,名称为ObjConfig.xml放在程序根目录供容器初始化
xml
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns='http://www.springframework.net' default-autowire="byType">
<!--这个配置文件主要用来配置系统的业务服务类,不要删除、修改提交其他人添加的配置,新加配置提交时主要同时提交配置使用的动态库,-->
<!--否则会造成其他人更新后报错-->
<!--检验数据访问层底层。postgresql配LIS.DAL.Base.PostgreSqlBase-->
<object id="LisMianDbFactory" type="LIS.Dal.Base.PostgreSqlBase,LIS.Dal.Base" singleton="false">
</object>
</objects>
容器实现
java
package LIS.Core.Context;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.lang.reflect.Type;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.HashMap;
import java.util.*;
//一个迷你版容器,供ORM等控制反转使用
public class ObjectContainer {
///用来存类型
private static List<Class> classList=new ArrayList<Class>();
///存类的查找关系
private static HashMap<String, Integer> classIndexMap = new HashMap<String, Integer>();
/// <summary>
/// 按类型返回强类型的对象,一般用接口获得实现类
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <returns>返回的对象</returns>
public static <T> T GetObject()
{
Type type = ObjectContainer.class.getClass().getGenericSuperclass();
Class c=type.getClass();
Class<?> parent=c.getSuperclass();
String cName=c.getName();
if(classIndexMap.containsKey(cName))
{
//创建对象
Object o = GetObject(cName);
return (T)o;
}
if(parent!=null)
{
String parentName=parent.getName();
if(classIndexMap.containsKey(parentName))
{
//创建对象
Object o = GetObject(parentName);
return (T)o;
}
}
Class<?> interfaceArr[]=c.getInterfaces();
if(interfaceArr!=null&&interfaceArr.length>0)
{
for(int j=0;j<interfaceArr.length;j++)
{
String interfaceName=interfaceArr[j].getName();
if(classIndexMap.containsKey(interfaceName))
{
//创建对象
Object o = GetObject(interfaceName);
return (T)o;
}
}
}
return null;
}
/// <summary>
/// 按名称返回强类型的对象
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="name">对象名称</param>
/// <returns>返回的对象</returns>
public static <T> T GetTypeObject(String name)
{
Object o=GetObject(name);
return (T)o;
}
/// <summary>
/// 按名称返回对象
/// </summary>
/// <param name="name">对象名称</param>
/// <returns>返回对象</returns>
public static Object GetObject(String name)
{
if(classIndexMap.containsKey(name))
{
try {
int index=classIndexMap.get(name);
Class c=classList.get(index);
//创建对象
Object o = c.newInstance();
return o;
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
return null;
}
/// <summary>
/// 用类型全名和程序集全名获得类型
/// </summary>
/// <param name="typeName">类型全名</param>
/// <param name="assemblyName">程序集名</param>
/// <returns></returns>
private static Class GetType(String typeName, String assemblyName)
{
try {
//得到根路径
Class<?> clazz = ObjectContainer.class;
ClassLoader classLoader = clazz.getClassLoader();
URL resourceURL1 = classLoader.getResource("");
String bashePath = resourceURL1.getFile();
//组装成jar包路径
String jarPath=bashePath+assemblyName+".jar";
File file = new File(jarPath);
if (!file.exists()) {
throw new Exception("未能找到"+jarPath+"的文件");
}
//反射得到类型
//自己生成jar包路径
URL url = file.toURI().toURL();
URL[] urls = new URL[]{url};
//加载程序集
URLClassLoader loader = new URLClassLoader(urls);
//加载类
Class c = loader.loadClass(typeName);
if(c!=null)
{
return c;
}
else
{
throw new Exception("未能构建类型"+typeName);
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
return null;
}
/// <summary>
/// 从根目录的ObjConfig初始化IOC容器,还是按Spring.Net的配置格式
/// </summary>
public static void InitIoc() {
try {
//得到根路径
Class<?> clazz = ObjectContainer.class;
ClassLoader classLoader = clazz.getClassLoader();
URL resourceURL = classLoader.getResource("resources/ObjConfig.xml");
String IocPath = resourceURL.getFile();
//判断配置是否存在
File file = new File(IocPath);
if (!file.exists()) {
System.out.println("resources/ObjConfig.xml文件不存在,请确认!");
return;
}
//解析xml
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(file);
// 获得根节点
Element rootElement = document.getDocumentElement();
// 获得根节点下的所有子节点
NodeList students = rootElement.getChildNodes();
for (int i = 0; i < students.getLength(); i++) {
// 由于节点多种类型,而一般我们需要处理的是元素节点
Node childNode = students.item(i);
// 元素节点就是非空的子节点,也就是还有孩子的子节点
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
Element childElement = (Element) childNode;
//不是对象配置元素就忽略
if(childElement.getNodeName()!= "object")
{
continue;
}
//解析类型配置
String type=childElement.getAttribute("type");
//是否单例
String singleton=childElement.getAttribute("singleton");
//取对象id
String id=childElement.getAttribute("id");
//分割类全面和包名
String [] arr=type.split(",");
//反射得到类型
Class c=GetType(arr[0],arr[1]);
//添加到类型列表
classList.add(c);
//存储索引
int index=classList.size()-1;
Class<?> parent=c.getSuperclass();
//有id就存id映射
if(id!=null&&id!="")
{
if(classIndexMap.containsKey(id))
{
throw new Exception("已经包含了id为:"+id+"的类型");
}
classIndexMap.put(id,index);
}
//有父类就存父类映射
if(parent!=null)
{
String parentName=parent.getName();
if(!classIndexMap.containsKey(parentName))
{
classIndexMap.put(parentName,index);
}
}
//得到所有实现的接口
Class<?> interfaceArr[]=c.getInterfaces();
//循环存接口映射
if(interfaceArr!=null&&interfaceArr.length>0)
{
for(int j=0;j<interfaceArr.length;j++)
{
String interfaceName=interfaceArr[j].getName();
if(!classIndexMap.containsKey(interfaceName)) {
classIndexMap.put(interfaceName, index);
}
}
}
}
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
使用容器
运行测试,成功取到PG数据库的数据
经过下午两小时的努力,LIS.Core的一个核心小功能实现了