一、Spring容器简介

一说起Spring框架,其最原始最核心的便是Spring容器了,当然随着Spring的不断发展,Spring也增加 诸如Security,Batch等框架,虽然它们是独立于Spring framework的。但是很多东西的核心基础还是Spring 容器的概念,所以可以说Spring容器是Spring的基石。而“容器”这个说法也是个相当形象的概念,这个所谓的Spring 容器简单的来说就是用来容纳Spring对象的(Spring beans)。它相当于一个工厂,可以在里面创建对象, 配置对象,管理对象的整个生命周期,直到对象销毁。但为什么又叫做IoC(Inversion of control)容器呢? 那么先来看看什么是IoC:

###控制反转(IoC)是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency_Injection,简称DI)

知道了IoC的概念,就简单多了。因为Spring容器就是采用依赖注入来组织对象的。至于如何组织的,那就是Spring的事情了。 它通过读取装有配置信息的配置元数据(configuration metadata)来创建,配置和装配对象。 这个配置元数据可以是XML,Java Annotation或者是Java代码。因为上述原因,所以可以称Spring容器为IoC容器。

二、Spring的两种容器

Spring框架提供了两种类型的容器如下:

  • Spring BeanFactory 容器。
  • Spring ApplicationContext 容器。

之前也说过,Spring容器相当一个工厂,这不上面出现了BeanFactory(Bean工厂)。BeanFactory容器是最简单的容器,提供基本的依赖注入, 由org.springframework.beans.factory.BeanFactory接口定义。由于要向后兼容,仍旧有很多第三方框架使用旧的接口,所以它还有一些其他相关接口,如BeanFactoryAware, InitializingBean, DisposableBean。 而那个ApplicationContext容器由org.springframework.context.ApplicationContext接口定义,它包括了BeanFactory容器的所有功能,且提供了比BeanFactory容器更多企业级应用的相关功能,例如解析properties文件中的文本, 将事件发布到监听事件的监听器。因此,在企业级应用中可能用的更多些。而对于那些轻量级的应用,如手机应用或者applet应用,需要内存的使用是你最大的瓶颈时,而且你又不需要用到ApplicationContext的很多功能的时候,可以使用BeanFactory。 知道了这些基础概念后,让我们来动手实践下吧。

三、创建基于BeanFactory容器的例子

首先引用相关的Spring包:spring-beans-3.2.4.RELEASE.jar和spring-core-3.2.4.RELEASE.jar。里面的-3.2.4.RELEASE部分 是版本号,你的可能和这里不一样。为什么我不把所有Spring引入?因为BeanFactory只用到这两个包的内容,把别的弄进来 太浪费了。接下来就可以写代码了:

  • 创建一个BeanFactoryDemo的类用来测试BeanFactory,然后再新建一个User类,代表用户类,User类如下:

    public class User {

    private String name;
    private String password;
    
    
    public User() {
    }
    
    
    public void setName(String name) {
        this.name = name;
    }
    
    
    public String getName() {
        return this.name;
    }
    
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    
    public String getPassword() {
        return this.password;
    }
    

    }

然后编写BeanFactory如下:

import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class BeanFactoryDemo {

    public static void main(String[] args) {
        XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("Beans.xml"));
        User user = (User) factory.getBean("user");
        System.out.println(user.getName());
    }

}

是不是很简单,首先定义了一个User类,然后在BeanFactory类中来使用这个类。如何使用的呢?我们看到 首先生成一个XmlBeanFactory(它是BeanFactory接口的一个实现类)一个从xml加载Bean的工厂类,这个工厂类的构造函数使用ClassPathResource 读取Beans.xml文件。然后使用factory.getBean(“user”)就获得User类的对象实例了,最后,我们试图打印 user对象的名字属性,是不是很神奇?我们没有new一个User啊,当然了,这就是Spring容器的工作嘛。user对象 从工厂中生产出来了,当然我们还缺少了Beans.xml文件,马上写起来:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

    <bean id="user" class="sk.spring.tuto.demo2.User">
        <property name="name" value="Sirk"></property>
    </bean>
</beans>

记得把上述Bean.xml文件放到java项目的src目录下,然后编译运行。结果出现异常:Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory 结果发现Spring还依赖org.apache.commons.logging包,我们加入后在编译运行,结果会打印出Sirk。仔细的马上 可以发现这个是在xml文件中定义的,哈哈,怎么回事?后续再讲,先这么用着。

四、创建基于ApplicationContext容器的例子

在创建之前先来了解下一些基本知识。相比于BeanFactory容器来说,ApplicationContext容器拥有更多的功能,这也就 意味着要引入更多的依赖包。该容器由org.springframework.context.ApplicationContext接口定义。关于该接口,由以下几种实现:

###FileSystemXmlApplicationContext

你需要提供这个xml文件的绝对路径给该类的构造器,这个容器就能从xml文件加载你定义好的beans。

###ClassPathXmlApplicationContext

对于这个容器,它也是通过传递构造函数的参数去加载beans,只不过传给它的不是物理绝对路径,而只需要一个定义bean的xml文件名, 但是该文件必须放在CLASSPATH下面。

###WebXmlApplicationContext

该容器从web应用内加载定义了beans的xml文件,在之后web部分会具体讲到。

接下来就来实践一下,首先:需要再引入包spring-context-3.2.4.RELEASE.jar和spring-context-support-3.2.4.RELEASE.jar,spring-expression-3.2.4.RELEASE.jar 然后新建ApplicationContextDemo类:

package sk.spring.tuto.demo2;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ApplicationContextDemo {

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("Beans.xml");
        User user = (User) ctx.getBean("user");
        System.out.println(user.getName());
    }
}

记得上述的Beans.xml放在src目录下编译,和BeanFactory的例子一样。下面再看FileSystemXmlApplicationContext 的例子:

package sk.spring.tuto.demo2;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class FileSystemXmlApplicationContextDemo {
    public static void main(String[] args) {
        ApplicationContext ctx = new FileSystemXmlApplicationContext("d:/Beans.xml");
        User user = (User) ctx.getBean("user");
        System.out.println(user.getName());

    }
}

记得把Beans.xml放到相应的路径下,这里的示例是d盘下。如果没什么意外,这些例子最终运行会打印:Sirk。

五、总结

最后来总结下IoC容器工作的基本步骤:

  • 首先容器去相应的地方加载定义了beans的xml文件。然后上下文创建了一个Factory(工厂)Bean。 接着,相应的容器会创建并初始化在xml文件中的各个beans对象。
  • 然后通过getBean方法去获得需要的对象。例如例子中通过getBean(“user”)获得User对象。这里的参数“user”就是 xml文件中bean的id。通过该id查找到对象并返回,最终转换成User对象。然后就和你用new出来的对象一样,对这个对象 调用相应的类方法等等等…

参考:http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/overview.html

##文档信息