2.Spring IoC 容器

1.Spring IoC 容器

IoC 容器

Spring 容器是 Spring 框架的核心。容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁。Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件。这些对象被称为 Spring Beans,我们将在下一章中进行讨论。

通过阅读配置元数据提供的指令,容器知道对哪些对象进行实例化,配置和组装。配置元数据可以通过 XML,Java 注释或 Java 代码来表示。下图是 Spring 如何工作的高级视图。 Spring IoC 容器利用 Java 的 POJO 类和配置元数据来生成完全配置和可执行的系统或应用程序。

IOC 容器具有依赖注入功能的容器,它可以创建对象,IOC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。通常new一个实例,控制权由程序员控制,而"控制反转"是指new实例工作不由程序员来做而是交给Spring容器来做。在Spring中BeanFactory是IOC容器的实际代表者。

Spring 提供了以下两种不同类型的容器。

序号容器 & 描述

1Spring BeanFactory 容器

它是最简单的容器,给 DI 提供了基本的支持,它用 org.springframework.beans.factory.BeanFactory 接口来定义。BeanFactory 或者相关的接口,如 BeanFactoryAware,InitializingBean,DisposableBean,在 Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的。

2Spring ApplicationContext 容器

该容器添加了更多的企业特定的功能,例如从一个属性文件中解析文本信息的能力,发布应用程序事件给感兴趣的事件监听器的能力。该容器是由 org.springframework.context.ApplicationContext 接口定义。

ApplicationContext 容器包括 BeanFactory 容器的所有功能,所以通常建议超过 BeanFactory。BeanFactory 仍然可以用于轻量级的应用程序,如移动设备或基于 applet 的应用程序,其中它的数据量和速度是显著。


2.Spring BeanFactory 容器

Spring 的 BeanFactory 容器

这是一个最简单的容器,它主要的功能是为依赖注入 (DI) 提供支持,这个容器接口在 org.springframework.beans.factory.BeanFactor 中被定义。BeanFactory 和相关的接口,比如BeanFactoryAware、DisposableBean、InitializingBean,仍旧保留在 Spring 中,主要目的是向后兼容已经存在的和那些 Spring 整合在一起的第三方框架。

在 Spring 中,有大量对 BeanFactory 接口的实现。其中,最常被使用的是 XmlBeanFactory 类。这个容器从一个 XML 文件中读取配置元数据,由这些元数据来生成一个被配置化的系统或者应用。

在资源宝贵的移动设备或者基于 applet 的应用当中, BeanFactory 会被优先选择。否则,一般使用的是 ApplicationContext,除非你有更好的理由选择 BeanFactory。

例子:

假设我们已经安装 Eclipse IDE,按照下面的步骤,我们可以创建一个 Spring 应用程序。

步骤描述

1创建一个名为 SpringExample 的工程并在 src 文件夹下新建一个名为 com.tutorialspoint 文件夹。

2点击右键,选择 Add External JARs 选项,导入 Spring 的库文件,正如我们在 Spring Hello World Example 章节中提到的导入方式。

3在 com.tutorialspoint 文件夹下创建 HelloWorld.java 和 MainApp.java 两个类文件。

4在 src 文件夹下创建 Bean 的配置文件 Beans.xml

5最后的步骤是创建所有 Java 文件和 Bean 的配置文件的内容,按照如下所示步骤运行应用程序。

下面是文件 HelloWorld.java 的内容:

packagecom.tutorialspoint;publicclassHelloWorld{privateString message;publicvoidsetMessage(String message){this.message  = message;  }publicvoidgetMessage(){    System.out.println("Your Message : "+ message);  }}

下面是文件 MainApp.java 的内容:

packagecom.tutorialspoint;importorg.springframework.beans.factory.InitializingBean;importorg.springframework.beans.factory.xml.XmlBeanFactory;importorg.springframework.core.io.ClassPathResource;publicclassMainApp{publicstaticvoidmain(String[] args){      XmlBeanFactory factory =newXmlBeanFactory                            (newClassPathResource("Beans.xml"));      HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");      obj.getMessage();  }}

在主程序当中,我们需要注意以下两点:

第一步利用框架提供的 XmlBeanFactory() API 去生成工厂 bean 以及利用 ClassPathResource() API 去加载在路径 CLASSPATH 下可用的 bean 配置文件。XmlBeanFactory() API 负责创建并初始化所有的对象,即在配置文件中提到的 bean。

第二步利用第一步生成的 bean 工厂对象的 getBean() 方法得到所需要的 bean。 这个方法通过配置文件中的 bean ID 来返回一个真正的对象,该对象最后可以用于实际的对象。一旦得到这个对象,你就可以利用这个对象来调用任何方法。

下面是配置文件 Beans.xml 中的内容:

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

如果你已经完成上面的内容,接下来,让我们运行这个应用程序。如果程序没有错误,你将从控制台看到以下信息:

Your Message : Hello World!



3.Spring ApplicationContext 容器

Spring ApplicationContext 容器

Application Context 是 BeanFactory 的子接口,也被成为 Spring 上下文。

Application Context 是 spring 中较高级的容器。和 BeanFactory 类似,它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean。 另外,它增加了企业所需要的功能,比如,从属性文件中解析文本信息和将事件传递给所指定的监听器。这个容器在 org.springframework.context.ApplicationContext interface 接口中定义。

ApplicationContext 包含 BeanFactory 所有的功能,一般情况下,相对于 BeanFactory,ApplicationContext 会更加优秀。当然,BeanFactory 仍可以在轻量级应用中使用,比如移动设备或者基于 applet 的应用程序。

最常被使用的 ApplicationContext 接口实现:

FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径。

ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。

WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。

我们已经在 Spring Hello World Example章节中看到过 ClassPathXmlApplicationContext 容器,并且,在基于 spring 的 web 应用程序这个独立的章节中,我们讨论了很多关于 XmlWebApplicationContext。所以,接下来,让我们看一个关于 FileSystemXmlApplicationContext 的例子。

例子:

假设我们已经安装 Eclipse IDE,按照下面的步骤,我们可以创建一个 Spring 应用程序。

步骤描述

1创建一个名为 SpringExample 的工程, 在 src 下新建一个名为 com.tutorialspoint 的文件夹src

2点击右键,选择 Add External JARs 选项,导入 Spring 的库文件,正如我们在 Spring Hello World Example 章节中提到的导入方式。

3在 com.tutorialspoint 文件夹下创建 HelloWorld.java 和 MainApp.java 两个类文件。

4文件夹下创建 Bean 的配置文件 Beans.xml。

5最后的步骤是编辑所有 JAVA 文件的内容和 Bean 的配置文件,按照以前我们讲的那样去运行应用程序。

下面是文件 HelloWorld.java 的内容:

packagecom.tutorialspoint;publicclassHelloWorld{privateString message;publicvoidsetMessage(String message){this.message  = message;  }publicvoidgetMessage(){      System.out.println("Your Message : "+ message);  }}

下面是文件 MainApp.java 的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.FileSystemXmlApplicationContext;publicclassMainApp{publicstaticvoidmain(String[] args){      ApplicationContext context =newFileSystemXmlApplicationContext            ("C:/Users/ZARA/workspace/HelloSpring/src/Beans.xml");      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");      obj.getMessage();  }}

在主程序当中,我们需要注意以下两点:

第一步生成工厂对象。加载完指定路径下 bean 配置文件后,利用框架提供的 FileSystemXmlApplicationContext API 去生成工厂 bean。FileSystemXmlApplicationContext 负责生成和初始化所有的对象,比如,所有在 XML bean 配置文件中的 bean。

第二步利用第一步生成的上下文中的 getBean() 方法得到所需要的 bean。 这个方法通过配置文件中的 bean ID 来返回一个真正的对象。一旦得到这个对象,就可以利用这个对象来调用任何方法。

下面是配置文件 Beans.xml 中的内容:

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">         

如果你已经完成上面的内容,接下来,让我们运行这个应用程序。如果程序没有错误,你将从控制台看到以下信息:

Your Message : Hello World!


4.Spring Bean 定义

Bean 定义

被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的,例如,已经在先前章节看到的,在 XML 的表单中的 定义。

bean 定义包含称为配置元数据的信息,下述容器也需要知道配置元数据:

如何创建一个 bean

bean 的生命周期的详细信息

bean 的依赖关系

上述所有的配置元数据转换成一组构成每个 bean 定义的下列属性。

属性描述

class这个属性是强制性的,并且指定用来创建 bean 的 bean 类。

name这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID 和/或 name 属性来指定 bean 标识符。

scope这个属性指定由特定的 bean 定义创建的对象的作用域,它将会在 bean 作用域的章节中进行讨论。

constructor-arg它是用来注入依赖关系的,并会在接下来的章节中进行讨论。

properties它是用来注入依赖关系的,并会在接下来的章节中进行讨论。

autowiring mode它是用来注入依赖关系的,并会在接下来的章节中进行讨论。

lazy-initialization mode延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。

initialization 方法在 bean 的所有必需的属性被容器设置之后,调用回调方法。它将会在 bean 的生命周期章节中进行讨论。

destruction 方法当包含该 bean 的容器被销毁时,使用回调方法。它将会在 bean 的生命周期章节中进行讨论。

Bean 与 Spring 容器的关系

下图表达了Bean 与 Spring 容器之间的关系:

Spring 配置元数据

Spring IoC 容器完全由实际编写的配置元数据的格式解耦。有下面三个重要的方法把配置元数据提供给 Spring 容器:

基于 XML 的配置文件

基于注解的配置

基于 Java 的配置

提示:对于基于 XML 的配置,Spring 2.0 以后使用 Schema 的格式,使得不同类型的配置拥有了自己的命名空间,是配置文件更具扩展性。

你已经看到了如何把基于 XML 的配置元数据提供给容器,但是让我们看看另一个基于 XML 配置文件的例子,这个配置文件中有不同的 bean 定义,包括延迟初始化,初始化方法和销毁方法的:

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">                                                 

在上述示例中:

①xmlns="http://www.springframework.org/schema/beans",默认命名空间:它没有空间名,用于Spring Bean的定义;

②xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance",xsi命名空间:这个命名空间用于为每个文档中命名空间指定相应的Schema样式文件,是标准组织定义的标准命名空间。

你可以查看 Spring Hello World 实例 来详细理解如何定义,配置和创建 Spring Beans。

关于基于注解的配置将在一个单独的章节中进行讨论。刻意把它保留在一个单独的章节,是因为我想让你在开始使用注解和 Spring 依赖注入编程之前,能掌握一些其他重要的 Spring 概念。



5.Spring Bean 作用域

Bean 的作用域

当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项。例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 singleton

Spring 框架支持以下五个作用域,分别为singleton、prototype、request、session和global session,5种作用域说明如下所示,

注意,如果你使用 web-aware ApplicationContext 时,其中三个是可用的。    

作用域描述

singleton在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值

prototype每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()

request每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境

session同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境

global-session一般用于Portlet应用环境,该运用域仅适用于WebApplicationContext环境

本章将讨论前两个范围,当我们将讨论有关 web-aware Spring ApplicationContext 时,其余三个将被讨论。

singleton 作用域:

singleton 是默认的作用域,也就是说,当定义 Bean 时,如果没有指定作用域配置项,则 Bean 的作用域被默认为 singleton。

当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。

也就是说,当将一个bean定义设置为singleton作用域的时候,Spring IoC容器只会创建该bean定义的唯一实例。

Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。你可以在 bean 的配置文件中设置作用域的属性为 singleton,如下所示:

例子

我们在适当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:

步骤描述

1创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint

2使用 Add External JARs 选项,添加所需的 Spring 库,在 Spring Hello World Example 章节解释。

3在 com.tutorialspoint 包中创建 Java 类 HelloWorld 和 MainApp

4在 src 文件夹中创建 Beans 配置文件 Beans.xml

5最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序,解释如下。

这里是 HelloWorld.java 文件的内容:

packagecom.tutorialspoint;publicclassHelloWorld{privateString message;publicvoidsetMessage(String message){this.message  = message;  }publicvoidgetMessage(){      System.out.println("Your Message : "+ message);  }}

下面是 MainApp.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassMainApp{publicstaticvoidmain(String[] args){      ApplicationContext context =newClassPathXmlApplicationContext("Beans.xml");      HelloWorld objA = (HelloWorld) context.getBean("helloWorld");      objA.setMessage("I'm object A");      objA.getMessage();      HelloWorld objB = (HelloWorld) context.getBean("helloWorld");      objB.getMessage();  }}

下面是 singleton 作用域必需的配置文件 Beans.xml

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

一旦你创建源代码和 bean 配置文件完成后,我们就可以运行该应用程序。如果你的应用程序一切都正常,将输出以下信息:

Your Message : I'm object A

Your Message : I'm object A

prototype 作用域

当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

为了定义 prototype 作用域,你可以在 bean 的配置文件中设置作用域的属性为 prototype,如下所示:

例子

我们在适当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:

步骤描述

1创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包com.tutorialspoint

2使用 Add External JARs 选项,添加所需的 Spring 库,解释见 Spring Hello World Example 章节。

3在 com.tutorialspoint 包中创建 Java 类 HelloWorld 和 MainApp

4在 src 文件夹中创建 Beans 配置文件Beans.xml

5最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序,解释如下所示。

这里是 HelloWorld.java 文件的内容:

packagecom.tutorialspoint;publicclassHelloWorld{privateString message;publicvoidsetMessage(String message){this.message  = message;  }publicvoidgetMessage(){      System.out.println("Your Message : "+ message);  }}

下面是 MainApp.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassMainApp{publicstaticvoidmain(String[] args){      ApplicationContext context =newClassPathXmlApplicationContext("Beans.xml");      HelloWorld objA = (HelloWorld) context.getBean("helloWorld");      objA.setMessage("I'm object A");      objA.getMessage();      HelloWorld objB = (HelloWorld) context.getBean("helloWorld");      objB.getMessage();  }}

下面是 prototype 作用域必需的配置文件 Beans.xml:

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">   

一旦你创建源代码和 Bean 配置文件完成后,我们就可以运行该应用程序。如果你的应用程序一切都正常,将输出以下信息:

Your Message : I'm object A

Your Message : null


6.Spring Bean 生命周期

Bean 的生命周期

理解 Spring bean 的生命周期很容易。当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态。同样,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作。

尽管还有一些在 Bean 实例化和销毁之间发生的活动,但是本章将只讨论两个重要的生命周期回调方法,它们在 bean 的初始化和销毁的时候是必需的。

为了定义安装和拆卸一个 bean,我们只要声明带有 init-method 和/或 destroy-method 参数的 。init-method 属性指定一个方法,在实例化 bean 时,立即调用该方法。同样,destroy-method 指定一个方法,只有从容器中移除 bean 之后,才能调用该方法。

Bean的生命周期可以表达为:Bean的定义——Bean的初始化——Bean的使用——Bean的销毁

初始化回调

org.springframework.beans.factory.InitializingBean 接口指定一个单一的方法:

voidafterPropertiesSet()throwsException;

因此,你可以简单地实现上述接口和初始化工作可以在 afterPropertiesSet() 方法中执行,如下所示:

publicclassExampleBeanimplementsInitializingBean{publicvoidafterPropertiesSet(){// do some initialization work}}

在基于 XML 的配置元数据的情况下,你可以使用 init-method 属性来指定带有 void 无参数方法的名称。例如:

下面是类的定义:

publicclassExampleBean{publicvoidinit(){// do some initialization work}}

销毁回调

org.springframework.beans.factory.DisposableBean 接口指定一个单一的方法:

voiddestroy()throwsException;

因此,你可以简单地实现上述接口并且结束工作可以在 destroy() 方法中执行,如下所示:

publicclassExampleBeanimplementsDisposableBean{publicvoiddestroy(){// do some destruction work}}

在基于 XML 的配置元数据的情况下,你可以使用 destroy-method 属性来指定带有 void 无参数方法的名称。例如:

下面是类的定义:

publicclassExampleBean{publicvoiddestroy(){// do some destruction work}}

如果你在非 web 应用程序环境中使用 Spring 的 IoC 容器;例如在丰富的客户端桌面环境中;那么在 JVM 中你要注册关闭 hook。这样做可以确保正常关闭,为了让所有的资源都被释放,可以在单个 beans 上调用 destroy 方法。

建议你不要使用 InitializingBean 或者 DisposableBean 的回调方法,因为 XML 配置在命名方法上提供了极大的灵活性。

例子

我们在适当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:

步骤描述

1创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint

2使用 Add External JARs 选项,添加所需的 Spring 库,解释见 Spring Hello World Example 章节。

3在 com.tutorialspoint 包中创建 Java 类 HelloWorld 和 MainApp

4在 src 文件夹中创建 Beans 配置文件 Beans.xml

5最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序,解释如下所示。

这里是 HelloWorld.java 的文件的内容:

packagecom.tutorialspoint;publicclassHelloWorld{privateString message;publicvoidsetMessage(String message){this.message  = message;  }publicvoidgetMessage(){      System.out.println("Your Message : "+ message);  }publicvoidinit(){      System.out.println("Bean is going through init.");  }publicvoiddestroy(){      System.out.println("Bean will destroy now.");  }}

下面是 MainApp.java 文件的内容。在这里,你需要注册一个在 AbstractApplicationContext 类中声明的关闭 hook 的 registerShutdownHook() 方法。它将确保正常关闭,并且调用相关的 destroy 方法。

packagecom.tutorialspoint;importorg.springframework.context.support.AbstractApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassMainApp{publicstaticvoidmain(String[] args){      AbstractApplicationContext context =newClassPathXmlApplicationContext("Beans.xml");      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");      obj.getMessage();      context.registerShutdownHook();  }}

下面是 init 和 destroy 方法必需的配置文件 Beans.xml 文件:

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">         

一旦你创建源代码和 bean 配置文件完成后,我们就可以运行该应用程序。如果你的应用程序一切都正常,将输出以下信息:

Bean is going through init.

Your Message : Hello World!

Bean will destroy now.

默认的初始化和销毁方法

如果你有太多具有相同名称的初始化或者销毁方法的 Bean,那么你不需要在每一个 bean 上声明初始化方法销毁方法。框架使用 元素中的 default-init-method 和 default-destroy-method 属性提供了灵活地配置这种情况,如下所示:

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"default-init-method="init"default-destroy-method="destroy">         


7.Spring Bean 后置处理器

Spring——Bean 后置处理器

Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理。

BeanPostProcessor 接口定义回调方法,你可以实现该方法来提供自己的实例化逻辑,依赖解析逻辑等。你也可以在 Spring 容器通过插入一个或多个 BeanPostProcessor 的实现来完成实例化,配置和初始化一个bean之后实现一些自定义逻辑回调方法。

你可以配置多个 BeanPostProcessor 接口,通过设置 BeanPostProcessor 实现的 Ordered 接口提供的 order 属性来控制这些 BeanPostProcessor 接口的执行顺序。

BeanPostProcessor 可以对 bean(或对象)实例进行操作,这意味着 Spring IoC 容器实例化一个 bean 实例,然后 BeanPostProcessor 接口进行它们的工作。

ApplicationContext 会自动检测由 BeanPostProcessor 接口的实现定义的 bean,注册这些 bean 为后置处理器,然后通过在容器中创建 bean,在适当的时候调用它。

例子:

下面的例子显示如何在 ApplicationContext 的上下文中编写,注册和使用 BeanPostProcessor。

我们在适当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:

步骤描述

1创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint

2使用 Add External JARs 选项,添加所需的 Spring 库,解释见 Spring Hello World Example 章节。

3在 com.tutorialspoint 包中创建 Java 类 HelloWorldInitHelloWorld 和 MainApp

4在 src 文件夹中创建 Beans 配置文件 Beans.xml

5最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序,解释如下所示。

这里是 HelloWorld.java 文件的内容:

packagecom.tutorialspoint;publicclassHelloWorld{privateString message;publicvoidsetMessage(String message){this.message  = message;  }publicvoidgetMessage(){      System.out.println("Your Message : "+ message);  }publicvoidinit(){      System.out.println("Bean is going through init.");  }publicvoiddestroy(){      System.out.println("Bean will destroy now.");  }}

这是实现 BeanPostProcessor 的非常简单的例子,它在任何 bean 的初始化的之前和之后输入该 bean 的名称。你可以在初始化 bean 的之前和之后实现更复杂的逻辑,因为你有两个访问内置 bean 对象的后置处理程序的方法。

这里是 InitHelloWorld.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.beans.factory.config.BeanPostProcessor;importorg.springframework.beans.BeansException;publicclassInitHelloWorldimplementsBeanPostProcessor{publicObjectpostProcessBeforeInitialization(Object bean, String beanName)throwsBeansException{      System.out.println("BeforeInitialization : "+ beanName);returnbean;// you can return any other object as well}publicObjectpostProcessAfterInitialization(Object bean, String beanName)throwsBeansException{      System.out.println("AfterInitialization : "+ beanName);returnbean;// you can return any other object as well}}

下面是 MainApp.java 文件的内容。在这里,你需要注册一个在 AbstractApplicationContext 类中声明的关闭 hook 的 registerShutdownHook() 方法。它将确保正常关闭,并且调用相关的 destroy 方法。

packagecom.tutorialspoint;importorg.springframework.context.support.AbstractApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassMainApp{publicstaticvoidmain(String[] args){      AbstractApplicationContext context =newClassPathXmlApplicationContext("Beans.xml");      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");      obj.getMessage();      context.registerShutdownHook();  }}

下面是 init 和 destroy 方法需要的配置文件 Beans.xml 文件:

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

一旦你创建源代码和 bean 配置文件完成后,我们就可以运行该应用程序。如果你的应用程序一切都正常,将输出以下信息:

BeforeInitialization : helloWorld

Bean is going through init.

AfterInitialization : helloWorld

Your Message : Hello World!

Bean will destroy now.



8.Spring Bean 定义继承

Bean 定义继承

bean 定义可以包含很多的配置信息,包括构造函数的参数,属性值,容器的具体信息例如初始化方法,静态工厂方法名,等等。

子 bean 的定义继承父定义的配置数据。子定义可以根据需要重写一些值,或者添加其他值。

Spring Bean 定义的继承与 Java 类的继承无关,但是继承的概念是一样的。你可以定义一个父 bean 的定义作为模板和其他子 bean 就可以从父 bean 中继承所需的配置。

当你使用基于 XML 的配置元数据时,通过使用父属性,指定父 bean 作为该属性的值来表明子 bean 的定义。

例子

我们在适当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:

步骤描述

1创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint

2使用 Add External JARs 选项,添加所需的 Spring 库,解释见 Spring Hello World Example 章节。

3在 com.tutorialspoint 包中创建 Java 类 HelloWorldHelloIndia 和 MainApp

4在 src 文件夹中创建 Beans 配置文件 Beans.xml

5最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序,解释如下所示。

下面是配置文件 Beans.xml,在该配置文件中我们定义有两个属性 message1 和 message2 的 “helloWorld” bean。然后,使用 parent 属性把 “helloIndia” bean 定义为 “helloWorld” bean 的孩子。这个子 bean 继承 message2 的属性,重写 message1 的属性,并且引入一个属性 message3

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

这里是 HelloWorld.java 文件的内容:

package com.tutorialspoint;

public class HelloWorld {

  private String message1;

  private String message2;

  public void setMessage1(String message){

      this.message1  = message;

  }

  public void setMessage2(String message){

      this.message2  = message;

  }

  public void getMessage1(){

      System.out.println("World Message1 : " + message1);

  }

  public void getMessage2(){

      System.out.println("World Message2 : " + message2);

  }

}

这里是 HelloIndia.java 文件的内容:

package com.tutorialspoint;

public class HelloIndia {

  private String message1;

  private String message2;

  private String message3;

  public void setMessage1(String message){

      this.message1  = message;

  }

  public void setMessage2(String message){

      this.message2  = message;

  }

  public void setMessage3(String message){

      this.message3  = message;

  }

  public void getMessage1(){

      System.out.println("India Message1 : " + message1);

  }

  public void getMessage2(){

      System.out.println("India Message2 : " + message2);

  }

  public void getMessage3(){

      System.out.println("India Message3 : " + message3);

  }

}

下面是 MainApp.java 文件的内容:

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {

  public static void main(String[] args) {

      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");

      HelloWorld objA = (HelloWorld) context.getBean("helloWorld");

      objA.getMessage1();

      objA.getMessage2();

      HelloIndia objB = (HelloIndia) context.getBean("helloIndia");

      objB.getMessage1();

      objB.getMessage2();

      objB.getMessage3();

  }

}

一旦你创建源代码和 bean 配置文件完成后,我们就可以运行该应用程序。如果你的应用程序一切都正常,将输出以下信息:

World Message1 : Hello World!

World Message2 : Hello Second World!

India Message1 : Hello India!

India Message2 : Hello Second World!

India Message3 : Namaste India!

在这里你可以观察到,我们创建 “helloIndia” bean 的同时并没有传递 message2,但是由于 Bean 定义的继承,所以它传递了 message2。

Bean 定义模板

你可以创建一个 Bean 定义模板,不需要花太多功夫它就可以被其他子 bean 定义使用。在定义一个 Bean 定义模板时,你不应该指定的属性,而应该指定带 true 值的抽象属性,如下所示:

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

父 bean 自身不能被实例化,因为它是不完整的,而且它也被明确地标记为抽象的。当一个定义是抽象的,它仅仅作为一个纯粹的模板 bean 定义来使用的,充当子定义的父定义使用。

你可能感兴趣的:(2.Spring IoC 容器)