产品的需求越来越多,则开发了越来越多的功能,同时也带来了越来越多的第三方library.这要是做server也就无所谓了,问题是我现在的这个东东,是个C/S的。看着Client里面越来越多的第三方jar,日益扩大的安装文件,这是个问题。
Client用到了Spring作为IOC容器来构造所有swing组件以及后台Bean,仔细分析了下,也就只用到了spring的IOC,最简单的Spring-core.jar都是好几百K。IOC的功能也不算很复杂,自己就尝试实现了一个简陋版的。
实现的原理其实很简单,第一步,java读取Spring格式的Bean配置文件,放入一个大的Map中;第二步,循环Map,根据存储信息,用反射依次生成这些实例,简单类型就直接赋值,需要ref Bean的就递归下去。如果是aop就用动态代理的方式来实现,最后都放入一个大的Map中。最后一步,反射调用配置的init方法,如果没配,就不管了。
首先是基本的结构
然后是读取配置加载到Map的片段:
再是反射加载类的片段:
到这里,所有的实例已经完整的加载到Map中去了。调用的时候直接用getBean()方法调用就可以了,就像Spring的ApplicationContext.getBean()一样。我就用这个在保持配置文件不变的情况下,将系统中用到Spring的地方全部去掉了,引用的lib从800多K降低到20多K,虽然实现得不完美,没有生命周期管理等,代码也写得不够优美,基本够用了。
Client用到了Spring作为IOC容器来构造所有swing组件以及后台Bean,仔细分析了下,也就只用到了spring的IOC,最简单的Spring-core.jar都是好几百K。IOC的功能也不算很复杂,自己就尝试实现了一个简陋版的。
实现的原理其实很简单,第一步,java读取Spring格式的Bean配置文件,放入一个大的Map中;第二步,循环Map,根据存储信息,用反射依次生成这些实例,简单类型就直接赋值,需要ref Bean的就递归下去。如果是aop就用动态代理的方式来实现,最后都放入一个大的Map中。最后一步,反射调用配置的init方法,如果没配,就不管了。
首先是基本的结构
public class Bean {
private String id;//bean的id,对应配置中的id
private String type;//bean的类型,对应配置中的class
private String init;//init方法的名字,对应配置中的init
private boolean singlton = true;//是否是单例,对应配置中的singlton
private Map mProperty = new HashMap();//Bean内部的<property>配置
private List constructorList = new ArrayList();//构造器的列表,对应<constructor-arg>配置
private Object bean;//真正的Bean实例
......
然后是读取配置加载到Map的片段:
public static Map loadXml(String fileName) {
fileName = Thread.currentThread().getContextClassLoader().getResource(
fileName).getPath().substring(1);
log.log(Level.FINE, "load xml:" + fileName);
Map<String, Bean> beansMap = new HashMap<String, Bean>();
DocumentBuilder documentBuilder;
try {
documentBuilder = getDocumentBuilder();
Document document = documentBuilder.parse(new File(fileName));
Element root = document.getDocumentElement();
NodeList childList = selectNodes("/beans/bean", root);
for (int i = 0; i < childList.getLength(); i++) {
Element currentNode = (Element) childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
Bean bean = new Bean();
String beanId = currentNode.getAttribute("id").trim();
String beanType = currentNode.getAttribute("class").trim();
if(null != currentNode.getAttributes().getNamedItem("init-method")) {
bean.setInit(currentNode.getAttributes().getNamedItem("init-method").getNodeValue());
}
if(null != currentNode.getAttributes().getNamedItem("singlton")) {
bean.setSinglton(new Boolean(currentNode.getAttributes().getNamedItem("singlton").getNodeValue()).booleanValue());
}
bean.setId(beanId);
bean.setType(beanType);
NodeList children = currentNode.getChildNodes();
for (int j = 0; j < children.getLength(); j++) {
if (children.item(j).getNodeType() == Node.TEXT_NODE) {
continue;
}
Element properties = (Element) children.item(j);
if (properties.getNodeName().equals("property")) {
String name = properties.getAttribute("name");
Element element = getElement(properties);
if (element == null) {
continue;
}
if (element.getNodeName().equals("value")) {
bean.getMProperty().put(name,
getTextValue(element));
} else if (element.getNodeName().equals("ref")) {
String[] refString = new String[] { element
.getAttribute("bean") };
bean.getMProperty().put(name, refString);
} else if (element.getNodeName().equals("list")) {
List valuesList = new ArrayList();
NodeList values = element.getChildNodes();
for (int k = 0; k < values.getLength(); k++) {
if (values.item(k).getNodeType() == Node.TEXT_NODE) {
continue;
}
Element valueP = (Element) values.item(k);
if (valueP.getNodeName().equals("value")) {
valuesList.add(getTextValue(valueP));
} else if (valueP.getNodeName().equals(
"ref")) {
valuesList.add(new String[] { valueP
.getAttribute("bean") });
}
}
bean.getMProperty().put(name, valuesList);
} else if (element.getNodeName().equals("props")) {
Map propertiesMap = new LinkedHashMap();
NodeList entries = element.getChildNodes();
for (int k = 0; k < entries.getLength(); k++) {
if (entries.item(k).getNodeType() == Node.TEXT_NODE) {
continue;
}
Element entry = (Element) entries.item(k);
String key = entry.getAttribute("key");
String value = getTextValue(entry);
propertiesMap.put(key, value);
}
bean.getMProperty().put(name, propertiesMap);
}
} else if (properties.getNodeName().equals(
"constructor-arg")) {
Constructs constructs = new Constructs();
if (null != properties.getAttributes().getNamedItem("value")) {
constructs.setValue(properties.getAttributes().getNamedItem("value").getNodeValue());
if (null != properties.getAttribute("type")) {
constructs.setType(properties
.getAttribute("type"));
}
bean.getConstructorList().add(constructs);
} else {
Element refE = getElement(properties);
constructs.setValue(new String[] { refE
.getAttribute("bean") });
bean.getConstructorList().add(constructs);
}
}
}
beansMap.put(beanId, bean);
break;
}
}
} catch (Exception e) {
throw new BeanException(e);
}
return beansMap;
再是反射加载类的片段:
private void initFactory() {
Iterator itr = beansMap.entrySet().iterator();
while(itr.hasNext()) {
Entry entry = (Entry)itr.next();
Object obj = getBean((String)entry.getKey());
Bean bean = (Bean)entry.getValue();
if(null != bean.getInit()) {
log.info("Now init bean:[" + (String)entry.getKey() + "] type[" + bean.getType()+"]");
//有init方法就反射调用
Util.initMethod(bean, obj);
}
}
}
/**
* 根据名字获取Bean,有就直接获取没有就加载再返回
* @param beanName
* @return
*/
public Object getBean(String beanName) {
Bean bean = (Bean) beansMap.get(beanName);
if(bean.isSinglton()) {
return null == bean.getBean() ? generatObj(bean) : bean.getBean();
} else {
return generatObj(bean);
}
}
/**
* 加载Bean
* @param bean
* @return
*/
private Object generatObj(Bean bean) {
String beanType = bean.getType();
Object obj = null;
//先根据构造器初始化
if(bean.getConstructorList().size() > 0) {
Object[] parameters = new Object[bean.getConstructorList().size()];
Class[] clazz = new Class[bean.getConstructorList().size()];
for(int i = 0;i < bean.getConstructorList().size();i++) {
Constructs arg = (Constructs)bean.getConstructorList().get(i);
if(arg.getValue() instanceof String) {
parameters[i] = Util.switchValue((String)arg.getValue(),arg.getType());
} else if(arg.getValue() instanceof String[]) {
parameters[i] = getBean(((String[]) arg.getValue())[0]);
}
clazz[i] = parameters[i].getClass();
}
obj = Util.newInstance(beanType,clazz,parameters);
}
//没有就直接初始化
if(null == obj){
obj = Util.newInstance(beanType);
}
if(bean.isSinglton()) {
bean.setBean(obj);
}
//aop的配置就用动态代理方式
if (obj instanceof ProxyFactoryBean) {
obj = getProxyBean(bean, obj);
} else {
setProperty(bean, obj);
}
if(bean.isSinglton()) {
bean.setBean(obj);
}
return obj;
}
//加载动态代理类
private Object getProxyBean(Bean bean, Object obj) {
Map propertiesMap = bean.getMProperty();
Iterator keysIterator = propertiesMap.keySet().iterator();
String interfaceClass = null;
Object beanObj = null;
while (keysIterator.hasNext()) {
String proxyProperty = (String) keysIterator.next();
Object proxyValue = propertiesMap.get(proxyProperty);
// value
if (proxyValue instanceof String) {
interfaceClass = (String) proxyValue;
} else if (proxyValue instanceof String[]) {
String[] strsValue = (String[]) proxyValue;
if (strsValue.length == 1) {
String beanId = ((String[]) proxyValue)[0];
beanObj = getBean(beanId);
Util.setProperty(obj, proxyProperty, beanObj);
}
} else if (proxyValue instanceof List) {
Iterator valuesIterator = ((List) proxyValue).iterator();
List valuesList = new ArrayList();
while (valuesIterator.hasNext()) {
Object value = valuesIterator.next();
if (value instanceof String) {
valuesList.add(getBean((String) value));
}
}
Util.setProperty(obj, proxyProperty, valuesList);
}
}
if (null != interfaceClass && null != beanObj) {
if (!Util.includeInterfaceOrnot(beanObj, interfaceClass)) {
throw new BeanException("no interface implemented ");
}
}
Object proxyBean = ((ProxyFactoryBean) obj).getProxyObject();
return proxyBean;
}
//设置类的property
private void setProperty(Bean bean, Object obj) {
Map propertiesMap = bean.getMProperty();
Iterator keysIterator = propertiesMap.keySet().iterator();
while (keysIterator.hasNext()) {
String property = (String) keysIterator.next();
Object value = propertiesMap.get(property);
if (value instanceof String) {
Util.setProperty(obj, property, (String) value);
} else if (value instanceof String[]) {
String[] strsValue = (String[]) value;
if (strsValue.length == 1) {
String beanId = ((String[]) value)[0];
Util.setProperty(obj, property, getBean(beanId));
}
} else if (value instanceof List) {
Iterator valuesIterator = ((List) value).iterator();
List valuesList = new ArrayList();
while (valuesIterator.hasNext()) {
Object valueList = (Object) valuesIterator.next();
if (valueList instanceof String[]) { // ref
valuesList.add(getBean(((String[]) valueList)[0]));
}
}
Util.setProperty(obj, property, valuesList);
}else if (value instanceof Map) {
Util.setProperty(obj, property, value);
}
}
}
到这里,所有的实例已经完整的加载到Map中去了。调用的时候直接用getBean()方法调用就可以了,就像Spring的ApplicationContext.getBean()一样。我就用这个在保持配置文件不变的情况下,将系统中用到Spring的地方全部去掉了,引用的lib从800多K降低到20多K,虽然实现得不完美,没有生命周期管理等,代码也写得不够优美,基本够用了。