初步理解spring ioc原理(读完可自己实现依赖注入部分的spring框架)

来源:互联网 发布:linux telnet服务 编辑:程序博客网 时间:2024/05/24 07:15

spring  的核心原理是ioc 和aop(面向切面编程),近段时间学习了spring的ioc部分,这篇文章也是自己对spring  原理的一个理解整理,希望对大家有所帮助。aop待学习之后再发表文章。

ioc(控制反转) 是指有依赖关系的两个对象A和B,A对象的实现依赖B对象的实现,那么在通常开发中,我们会实例化一个b对象来让a对象进行调用,a对象掌握着b对象的生命周期,也就是说a对象控制着d对象,而这是高耦合性的。而在ioc中,将b对象的创建和管理交于第三者来代理(比如一个框架或者工具类),而b对象的实例化交给代理者来管理,a对象只负责使用b对象来进行业务处理,a对象对b对象的控制则交给了代理者,这就是控制反转的体现。而依赖注入,则是代理者利用ioc原理和类反射来动态注入a对象所依赖的对象(这里是b)。同时b对象只要是满足某一个接口(即a对象需要的部分)即可,那么可以将b对象作为一个接口类。这样更容易进行扩展。下面我会进一步剖析spring 的ioc部分,并带领大家完成自己 的ioc部分的spring框架。

首先新建一个web 工程, 导入dom4j.jar 和jaxen.jar 包,这是saxreader所依赖的包。saxreader 是一个优秀的xml解析api,我们使用它来解析spring bean配置文件。


在src下新建一个ms.xml文件作为spring 的配置文件

新建一个包,包里有以下两个文件

1.proxyXML.class  用于解析xml文件  

2.BeanFactory.class 用于获取xml文件的bean并注入所需实际引用对象


代码如下


1.proxyXML.class

import java.util.HashMap;import java.util.List;import java.util.Map;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;public class ProxyXML {private static Document xmldoc;static{//解析ms配置文件SAXReader saxReader = new SAXReader();try {xmldoc = saxReader.read(ProxyXML.class.getResourceAsStream("/ms.xml"));} catch (DocumentException e) {// TODO: handle exception}}//获取 配置文件中 beans节点里 name属性值为name 的bean的属性值并保存到map中返回public static Map getProperty(String name){String nodepath = "//beans/bean[@name='"+name+"']/property";//获取bean节点中所有的property子节点并保存到es中List<Element> es = xmldoc.selectNodes(nodepath);Map map = new HashMap();//对es进行遍历for(Element e :es){//如果该property有ref属性,那么保存ref的值并放在map中if(e.attribute("ref")!=null){map.put(e.attributeValue("name"),e.attributeValue("ref"));}else{//如果没有ref属性,那么认为是普通字符串进行保存Element ev = (Element) e.selectNodes("value").get(0);map.put(e.attributeValue("name"),ev.getText());}}return map;}}


2.BeanFactory.class 

import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.Map;public class BeanFactory {//根据传入的类名进行实例并返回类的实例,同时进行属性注入public Object getBeans(String name) throws Exception{//利用类反射机制实例类String classname = ProxyXML.getClass(name);Class clzz = Class.forName(classname);Object obj = clzz.newInstance();//获取该类的所有属性并进行注入实例Map map = ProxyXML.getProperty(name);if(map.size()>0){getMethod(obj,clzz,map);}return obj;}private void getMethod(Object obj, Class clzz, Map map) throws Exception {//获取clzz类的所有属性并进行遍历Field[] fs = clzz.getDeclaredFields();for(Field f :fs){//获取f的名字String mn = f.getName();//设置set方面名字为set和mn(mn第一个字母大写)String methodname = "set" +mn.substring(0,1).toUpperCase() + mn.substring(1);//生成method对象Method m =clzz.getMethod(methodname,f.getType());//如果f的类型是String那么直接掉用clzz的set方法,进行f属性注入if(f.getType().toString().endsWith("String")){m.invoke(obj, map.get(mn).toString());}else{//如果是类则先进行属性获取,再进行属性注入m.invoke(obj, getBeans(map.get(mn).toString()));}}}}

3.ms.xml

<?xml version="1.0" encoding="UTF-8"?><beans><bean name="print" class="com.sp.ms.Print"><property name="mes"><value>Hello SSH</value></property><property name="p" ref="paper"/><property name="b" ref="box"/></bean><bean name="paper" class="com.sp.ms.A4Paper"></bean><bean name="box" class="com.sp.ms.BlackBox"></bean></beans>


现在我们来对以上进行测试,先创建以几个类

1.Paper 接口类

2.Box接口类

3.A4paper 类 实现Paper 接口

4.Blackbox 类,实现 Box接口


1.Paper.class


package com.woniuxy.ms;public interface Paper {public abstract void doPaper();}

2.Box.class  

package com.woniuxy.ms;public interface Box {public abstract void doBox();}

3.A4paper.class


public class A4Paper implements Paper{@Overridepublic void doPaper() {System.out.print("此处约等于1000行代码-->");System.out.println("A4Paper");}}

4.Blackbox.class


public class BlackBox implements Box{@Overridepublic void doBox() {System.out.print("此处约等于1000行代码-->");System.out.println("黑色墨盒");}}

5.print.class


import com.sp.ms.util.BeanFactory;public class Print {//依赖注入private String mes;private Paper p;private Box b;public void setMes(String mes) {this.mes = mes;}public void setP(Paper p) {this.p = p;}public void setB(Box b) {this.b = b;}public void doPrint(){p.doPaper();b.doBox();System.out.println(mes);}public static void main(String[] args) throws Exception {Print p = (Print) new BeanFactory().getBeans("print");p.doPrint();}}

运行后结果如下:

//此处约等于1000行代码-->B5Paper//此处约等于1000行代码-->黑色墨盒//Hello SSH


以上就是对于spring ioc部分的整理,自己也有很多东西还没学透,各位观众老爷看看就好哈。


原创粉丝点击