spring IOC核心原理

下面来了解一下Spring到底是怎么运行的。

Java代码 
public static void main(String[] args) {   
        ApplicationContext context = new FileSystemXmlApplicationContext(   
                "applicationContext.xml");   
        Animal animal = (Animal) context.getBean("animal");   
        animal.say();   
    }  

这段代码你一定很熟悉吧,不过还是让我们分析一下它吧,首先是applicationContext.xml

Java代码 
<bean id="animal" class="phz.springframework.test.Cat">   
        <property name="name" value="kitty" />   
    </bean> 

他有一个类phz.springframework.test.Cat

Java代码 
public class Cat implements Animal {   
    private String name;   
    public void say() {   
        System.out.println("I am " + name + "!");   
    }   
    public void setName(String name) {   
        this.name = name;   
    }   
}  

 

实现了phz.springframework.test.Animal接口

Java代码 
public interface Animal {   
    public void say();   
}  

   

很明显上面的代码输出I am kitty! 

那么到底Spring是如何做到的呢? 
接下来就让我们自己写个Spring 来看看Spring 到底是怎么运行的吧! 

首先,我们定义一个Bean类,这个类用来存放一个Bean拥有的属性

Java代码 
/* Bean Id */  
    private String id;   
    /* Bean Class */  
    private String type;   
    /* Bean Property */  
    private Map<String, Object> properties = new HashMap<String, Object>();  

  

 

一个Bean包括id,type,和Properties。 

接下来Spring 就开始加载我们的配置文件了,将我们配置的信息保存在一个HashMap中,HashMap的key就是Bean 的 Id ,HasMap 的value是这个Bean,只有这样我们才能通过context.getBean("animal")这个方法获得Animal这个类。我们都知道Spirng可以注入基本类型,而且可以注入像List,Map这样的类型,接下来就让我们以Map为例看看Spring是怎么保存的吧 

Map配置可以像下面的

Java代码 
<bean id="test" class="Test">   
        <property name="testMap">   
            <map>   
                <entry key="a">   
                    <value>1</value>   
                </entry>   
                <entry key="b">   
                    <value>2</value>   
                </entry>   
            </map>   
        </property>   
    </bean>  

  

 

Spring是怎样保存上面的配置呢?,代码如下:

Java代码 
if (beanProperty.element("map") != null) {   
                    Map<String, Object> propertiesMap = new HashMap<String, Object>();   
                    Element propertiesListMap = (Element) beanProperty   
                            .elements().get(0);   
                    Iterator<?> propertiesIterator = propertiesListMap   
                            .elements().iterator();   
                    while (propertiesIterator.hasNext()) {   
                        Element vet = (Element) propertiesIterator.next();   
                        if (vet.getName().equals("entry")) {   
                            String key = vet.attributeValue("key");   
                            Iterator<?> valuesIterator = vet.elements()   
                                    .iterator();   
                            while (valuesIterator.hasNext()) {   
                                Element value = (Element) valuesIterator.next();   
                                if (value.getName().equals("value")) {   
                                    propertiesMap.put(key, value.getText());   
                                }   
                                if (value.getName().equals("ref")) {   
                                    propertiesMap.put(key, new String[] { value   
                                            .attributeValue("bean") });   
                                }   
                            }   
                        }   
                    }   
                    bean.getProperties().put(name, propertiesMap);   
                }  

  

接下来就进入最核心部分了,让我们看看Spring 到底是怎么依赖注入的吧,其实依赖注入的思想也很简单,它是通过反射机制实现的,在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中。让我们看看具体它是怎么做的吧。 
首先实例化一个类,像这样

Java代码 
public static Object newInstance(String className) {   
        Class<?> cls = null;   
        Object obj = null;   
        try {   
            cls = Class.forName(className);   
            obj = cls.newInstance();   
        } catch (ClassNotFoundException e) {   
            throw new RuntimeException(e);   
        } catch (InstantiationException e) {   
            throw new RuntimeException(e);   
        } catch (IllegalAccessException e) {   
            throw new RuntimeException(e);   
        }   
        return obj;   
    }  

  

接着它将这个类的依赖注入进去,像这样

Java代码 
public static void setProperty(Object obj, String name, String value) {   
        Class<? extends Object> clazz = obj.getClass();   
        try {   
            String methodName = returnSetMthodName(name);   
            Method[] ms = clazz.getMethods();   
            for (Method m : ms) {   
                if (m.getName().equals(methodName)) {   
                    if (m.getParameterTypes().length == 1) {   
                        Class<?> clazzParameterType = m.getParameterTypes()[0];   
                        setFieldValue(clazzParameterType.getName(), value, m,   
                                obj);   
                        break;   
                    }   
                }   
            }   
        } catch (SecurityException e) {   
            throw new RuntimeException(e);   
        } catch (IllegalArgumentException e) {   
            throw new RuntimeException(e);   
        } catch (IllegalAccessException e) {   
            throw new RuntimeException(e);   
        } catch (InvocationTargetException e) {   
            throw new RuntimeException(e);   
        }   
}  

  

最后它将这个类的实例返回给我们,我们就可以用了。我们还是以Map为例看看它是怎么做的,我写的代码里面是创建一个HashMap并把该HashMap注入到需要注入的类中,像这样,

Java代码 
if (value instanceof Map) {   
                Iterator<?> entryIterator = ((Map<?, ?>) value).entrySet()   
                        .iterator();   
                Map<String, Object> map = new HashMap<String, Object>();   
                while (entryIterator.hasNext()) {   
                    Entry<?, ?> entryMap = (Entry<?, ?>) entryIterator.next();   
                    if (entryMap.getValue() instanceof String[]) {   
                        map.put((String) entryMap.getKey(),   
                                getBean(((String[]) entryMap.getValue())[0]));   
                    }   
                }   
                BeanProcesser.setProperty(obj, property, map);   
            }  

  

好了,这样我们就可以用Spring 给我们创建的类了,是不是也不是很难啊?当然Spring能做到的远不止这些,这个示例程序仅仅提供了Spring最核心的依赖注入功能中的一部分。 

转载:http://blog.csdn.net/it_man/article/details/4402245

原文地址:https://www.cnblogs.com/tietazhan/p/6243801.html