`
flyPig
  • 浏览: 139590 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

简单的轮子--IOC容器

    博客分类:
  • Java
阅读更多
   产品的需求越来越多,则开发了越来越多的功能,同时也带来了越来越多的第三方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方法,如果没配,就不管了。

   首先是基本的结构
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,虽然实现得不完美,没有生命周期管理等,代码也写得不够优美,基本够用了。
分享到:
评论

相关推荐

    Spring概述与IOC.docx

    8. **集成性**:Spring 不重新发明轮子,它支持与其他流行框架和库的集成,如 Hibernate、MyBatis 等,提供了一站式解决方案,使得开发者可以专注于业务需求,而不是技术细节。 【IOC(Inversion of Control,控制...

    sunflower-ioc:Java编写的ioc工具

    sunflower-ioc这是一个基于注解的简易ioc工具, 为什么要重复造轮子呢, 只是为了好玩.:beaming_face_with_smiling_eyes:用法在Class上使用@Bean标注一个对象需要容器管理;在Field上使用@Resource标注依赖, 该field...

    在Struts 2中实现IoC

    下面,我们将深入探讨如何在Struts 2中实现IoC,并具体讲解其历史背景、实现步骤以及为何选择Spring作为IoC容器。 ### 历史背景 Struts 2框架源自WebWork,WebWork 2.2之前,其内部实现了一套控制反转机制。然而,...

    专题资料(2021-2022年)Spring面试题2016版资料.doc

    控制反转(IOC)是一种设计原则,它将对象的创建和管理责任从对象自身转移到外部容器,即Spring的IoC容器。在传统编程中,对象通常自行创建所需的依赖对象,而在IOC中,这些依赖是由容器在运行时动态地注入到对象中...

    spring+ajax+mybatis+springmvc笔记

    - IoC 是指对象之间的依赖关系由容器来建立,而不是由对象自身来建立。 - 这有助于降低对象间的耦合度。 - **3.2 依赖注入 (DI)** - DI 是 IoC 的具体实现方式,容器通过调用对象的 setter 方法或构造器来建立...

    java-spring经典教材

    - **IoC容器**:Inversion of Control (IoC) 容器是Spring的核心组件之一,负责管理对象的生命周期和配置。 - **AOP(面向切面编程)**:Spring提供了对AOP的支持,这有助于分离横切关注点(如日志记录、事务管理等...

    Spring第一天.pdf

    - **轮子理论**:Spring框架推崇“轮子理论”,即避免重复发明已有的组件或功能,而是尽可能地利用现有的成熟技术和工具。 - **宗旨**:Spring框架的宗旨在于不重新发明技术,而是让现有技术更加易用,提升开发效率...

    吴天雄--Spring笔记.doc

    它的核心目标是使开发过程变得简单,通过POJO(Plain Old Java Object)编程模型来促进良好的编程实践。Spring以其非侵入性著称,即它允许开发者在不依赖特定框架的情况下使用Java进行开发。尽管Spring本身是轻量级...

    Spring 实战基础

    1.spring:给软件行业带来了春天; 2.spring的理念:spring框架的初衷是使的现有的更加实用,spring不是创造轮子(技术或框架),而是... Ioc容器:控制反转;  Aop:面向切面编程;  对事务的支持;  对矿建的支持;

    Spring简介(ppt)

    例如,在阿里巴巴早期的系统中,可以看到各种Factory的使用,而Spring的IoC容器可以更优雅地管理这些对象的创建和依赖。 **面向切面编程(AOP)** AOP是Spring提供的一种处理横切关注点(如日志、事务管理)的方法...

    在EclipseRCP中实现反转控制(IoC)

    RCP使开发人员可以集中精力进行应用程序业务代码的开发,而不需要花费时间重新发明轮子编写应用程序管理的逻辑。反转控制(InversionofControl,IoC)和依赖注入(DependencyInjection,DI)是两种编程模式,可用于减少...

    详细介绍Spring框架 (2).pdf

    IoC使得对象的依赖关系由容器管理,而不是由对象自身负责,从而降低了耦合度。AOP则允许将系统级服务如日志、事务管理等与业务逻辑分离,提高了代码的可维护性和可复用性。 Spring框架不仅仅是一个简单的服务器端...

    传智168期JavaEE struts2杜宏 day 29~day31笔记.pdf

    - Struts2采用XWork核心,提供了前端拦截机(interceptor)、运行时表单属性验证、类型转换、表达式语言(OGNL)和IoC(控制反转)容器等功能。 3. Struts2框架在Web开发中的应用 - Struts2框架是在Java Web开发...

    today-context:Java Java库,用于依赖项注入和面向方面的编程

    today-web框架2.0刚出来时没有ioc容器感觉不是很方便,所以想自己实现一个。 :anxious_face_with_sweat:完全懵逼。之前学过怎么用Spring但是对他的完全完全不了解的我带着试一试的心态开始到处查资料,就这样我又...

    CommonLibrary.NET

    在CommonLibrary.NET中,可能包含了一套自定义的IOC容器,它能帮助开发者解耦代码,提高代码的可测试性和可维护性。 3. 验证扩展:验证是应用程序中不可或缺的一环,用于确保输入数据的有效性和安全性。这个库可能...

    大学毕业论文-—开源技术struts、spring、hibernate在mis开发中的应用研究.doc

    Spring的核心是IOC(Inversion of Control)容器,负责管理对象的生命周期和装配。此外,Spring还支持事务管理、数据访问集成、Web MVC框架等,使得开发者能方便地整合各种技术,如Hibernate。 3. **Hibernate**: ...

    基于SpringBoot和SpringCloud实现微服务架构学习(一).docx

    Spring Framework的核心特性包括IoC容器、AOP、数据访问/集成、事务管理等。 ##### 3.4 Spring Cloud Spring Cloud是一个基于Spring Boot实现的云应用开发工具包,它提供了微服务架构所需的一系列服务治理组件,...

Global site tag (gtag.js) - Google Analytics