文档章节

Spring IOC原理(二)

rabbit_mom
 rabbit_mom
发布于 2017/01/17 15:38
字数 1312
阅读 22
收藏 0

一、关于JavaBean理解

    相信每个码市小白每次读到Java Bean都感觉晦涩难懂,特此查了各大博客,搜寻到这些更容易理解的描述:

    它是符合一定操作规范编写的Java类(一个普通的Java类,但是我们对这个类有些要求):

1. 这个类需要是public 的, 然后需要有个无参数的构造函数

2. 这个类的属性应该是private 的, 通过setXXX()和getXXX()来访问

3. 这个类需要能支持“事件”, 例如addXXXXListener(XXXEvent e),  事件可以是Click事件,Keyboard事件

    等等, 当然咱们也支持自定义的事件。 

4. 我们得提供一个所谓的自省/反射机制, 这样能在运行时查看java bean 的各种信息“

5. 这个类应该是可以序列化的, 即可以把bean的状态保存的硬盘上, 以便以后来恢复。

    Java Bean可以理解为不是一种技术,而是一种规范。大家针对这种规范,总结了很多开发技巧、工具函

    数等,符合这种规范的类,可以被其它程序员或者框架使用。为了更好理解Java Bean,推荐两篇文章供

    参考:

    A、Java帝国之Java Bean(上)

http://mp.weixin.qq.com/s__biz=MzAxOTc0NzExNg==&mid=2665513115&idx=1&sn=da30cf3d3f163d478748fcdf721b6414#rd

    B、Java帝国之Java Bean(下)

http://mp.weixin.qq.com/s__biz=MzAxOTc0NzExNg==&mid=2665513118&idx=1&sn=487fefb8fa7efd59de6f37043eb21799#rd

二、运行

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看看到底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

上一篇: pom关系解析
rabbit_mom
粉丝 3
博文 25
码字总数 12119
作品 0
程序员
私信 提问
三条路线告诉你如何掌握Spring IoC容器的核心原理

一、前言 前三篇已经从历史的角度和大家一起探讨了为什么会有Spring,Spring的两个核心概念:IoC和AOP的雏形,Spring的历史变迁和如今的生态帝国。本节的主要目的就是通过一个切入点带大家一...

Java小铺
2018/08/27
0
0
那些年,我们一起追的Spring

学无止境,但仍需及时总结。 自去年开始写作以来,写了一些关于Spring的文章,今天将它们汇总起来,一方面方便大家阅读,另一方面,也是一次小的复盘总结。 IOC 首先是Spring的IOC,也就是控...

SexyCode
2018/08/14
0
0
面试阿里等互联网公司java岗位时,关于Spring到底需要掌握什么?

之前分享过一些BAT面试必会的文章,一些读者看了,问过我,Spring 这篇需要掌握一些什么?相信这个问题也是很多读者心中的疑问,今天就来聊一下关于 Spring,我从面试中收获的一些经验。 一....

别打我会飞
04/17
197
0
Spring集成 Struts2

Spring如何整合struts2? 1) 整合目标? 使IOC容器来管理Struts2的Action! 2) 如何进行整合? ① 正常加入Struts2 ② 在Spring的IOC容器中配置Struts2的Action 特别注意:在IOC容器中配置S...

哎小艾
2017/11/08
21
0
好程序员Java干货分享Spring框架之IOC原理

好程序员Java干货分享Spring框架之IOC原理,前言:Spring框架是我们进行企业级开发的最常用框架,本章我们将了解Spring框架,并学习Spring的IOC特性以及IOC的实现原理:注解和反射。 Spring...

好程序员IT
07/09
31
0

没有更多内容

加载失败,请刷新页面

加载更多

程序设计基础(C)第06讲例程

1summing.c /* summing.c -- 根据用户键入的整数求和 */#include <stdio.h>int main(void){ long num; long sum = 0L; /* 把sum 初始化为0 */ int status; p......

树人大学数字媒体吴凡
4分钟前
2
0
聊聊nacos config的publishConfig

序 本文主要研究一下nacos config的publishConfig ConfigController nacos-1.1.3/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java @Controller@R......

go4it
31分钟前
3
0
Eureka应用注册与集群数据同步源码解析

在之前的EurekaClient自动装配及启动流程解析一文中我们提到过,在构造DiscoveryClient类时,会把自身注册到服务端,本文就来分析一下这个注册流程 客户端发起注册 boolean register() t...

Java学习录
41分钟前
10
0
Java描述设计模式(15):责任链模式

本文源码:GitHub·点这里 || GitEE·点这里 一、生活场景描述 1、请假审批流程 公司常见的请假审批流程:请假天数 当 day<=3 天,项目经理审批当 3<day<=5 天,部门经理审批当 day>5 天...

知了一笑
52分钟前
10
0
总结:数组与链表

1、内存申请:数组在内存上是连续的空间;链表,内存地址上可以是不连续的。 2、查询速度:数组可以随机访问,链表必须顺序访问,即从首个元素开始遍历,逐个查找,所以数组查询很快。 3、写入...

浮躁的码农
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部