目录

Spring - 快速指南

Spring Framework - Overview

Spring是企业Java最流行的应用程序开发框架。 全球数百万开发人员使用Spring Framework创建高性能,易于测试和可重用的代码。

Spring框架是一个开源Java平台。 它最初由Rod Johnson编写,并于2003年6月首次在Apache 2.0许可下发布。

弹簧在尺寸和透明度方面很轻巧。 Spring框架的基本版本大约为2MB。

Spring Framework的核心功能可用于开发任何Java应用程序,但有一些扩展用于在Java EE平台之上构建Web应用程序。 Spring框架的目标是通过启用基于POJO的编程模型,使J2EE开发更易于使用并促进良好的编程实践。

使用Spring框架的好处

以下列出了使用Spring Framework的一些巨大好处 -

  • Spring使开发人员能够使用POJO开发企业级应用程序。 仅使用POJO的好处是您不需要EJB容器产品(如应用程序服务器),但您可以选择仅使用强大的servlet容器(如Tomcat)或某些商业产品。

  • Spring采用模块化方式组织。 即使包和类的数量很大,你也只需要担心你需要的那些而忽略其余的。

  • Spring并没有重新发明轮子,而是真正利用了一些现有技术,如几个ORM框架,日志框架,JEE,Quartz和JDK计时器以及其他视图技术。

  • 测试用Spring编写的应用程序很简单,因为依赖于环境的代码被移动到这个框架中。 此外,通过使用JavaBeanstyle POJO,使用依赖注入来注入测试数据变得更加容易。

  • Spring的Web框架是一个设计良好的Web MVC框架,它提供了一个很好的替代Web框架,如Struts或其他过度设计或不太流行的Web框架。

  • Spring提供了一个方便的API,用于将特定于技术的异常(例如,JDBC,Hibernate或JDO抛出)转换为一致的,未经检查的异常。

  • 轻量级IoC容器往往是轻量级的,尤其是与EJB容器相比时。 这有利于在具有有限内存和CPU资源的计算机上开发和部署应用程序。

  • Spring提供了一致的事务管理接口,可以缩小到本地事务(例如,使用单个数据库)并扩展到全局事务(例如,使用JTA)。

Dependency Injection (DI)

Spring最常见的技术是Inversion of Control的Dependency Injection (DI)风格。 Inversion of Control (IoC)是一个通用概念,它可以用许多不同的方式表达。 依赖注入只是控制反转的一个具体例子。

在编写复杂的Java应用程序时,应用程序类应尽可能独立于其他Java类,以增加重用这些类的可能性,并在单元测试时独立于其他类测试它们。 依赖注入有助于将这些类粘合在一起,同时保持它们的独立性。

究竟什么是依赖注入? 我们分别看看这两个词。 这里依赖部分转换为两个类之间的关联。 例如,A类依赖于B类。现在,让我们看第二部分,注入。 所有这些意味着,B类将由IoC注入A类。

依赖注入可以通过将参数传递给构造函数的方式发生,也可以通过使用setter方法进行后构建来实现。 由于依赖注入是Spring Framework的核心,我们将在一个单独的章节中通过相关示例来解释这个概念。

Aspect Oriented Programming (AOP)

Spring的一个关键组件是Aspect Oriented Programming (AOP)框架。 跨越应用程序多个点的功能称为cross-cutting concerns ,这些跨领域问题在概念上与应用程序的业务逻辑分开。 各方面有各种常见的良好示例,包括日志记录,声明式事务,安全性,缓存等。

OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面。 DI可帮助您将应用程序对象彼此分离,而AOP可帮助您将交叉问题与它们所影响的对象分离。

Spring Framework的AOP模块提供了面向方面的编程实现,允许您定义方法拦截器和切入点,以便干净地解耦实现应该分离的功能的代码。 我们将在另一章中讨论有关Spring AOP概念的更多信息。

Spring Framework - Architecture

Spring可能是所有企业应用程序的一站式商店。 但是,Spring是模块化的,允许您挑选和选择适用于您的模块,而无需引入其余模块。 以下部分提供有关Spring Framework中可用的所有模块的详细信息。

Spring Framework提供了大约20个可以根据应用程序需求使用的模块。

Spring框架架构

核心容器

核心容器由核心,Bean,上下文和表达式语言模块组成,其详细信息如下 -

  • Core模块提供了框架的基本部分,包括IoC和依赖注入功能。

  • Bean模块提供BeanFactory,它是工厂模式的复杂实现。

  • Context模块建立在Core和Beans模块提供的坚实基础之上,它是访问定义和配置的任何对象的媒介。 ApplicationContext接口是Context模块的焦点。

  • SpEL模块提供了一种强大的表达式语言,用于在运行时查询和操作对象图。

Data Access/Integration

数据访问/集成层由JDBC,ORM,OXM,JMS和Transaction模块组成,其详细信息如下 -

  • JDBC模块提供了JDBC抽象层,无需繁琐的JDBC相关编码。

  • ORM模块为流行的对象关系映射API提供集成层,包括JPA,JDO,Hibernate和iBatis。

  • OXM模块提供了一个抽象层,支持JAXB,Castor,XMLBeans,JiBX和XStream的Object/XML映射实现。

  • Java Messaging Service JMS模块包含用于生成和使用消息的功能。

  • Transaction模块支持对实现特殊接口和所有POJO的类进行编程和声明式事务管理。

Web

Web层由Web,Web-MVC,Web-Socket和Web-Portlet模块组成,其详细信息如下 -

  • Web模块提供基本的面向Web的集成功能,例如多部分文件上载功能以及使用servlet侦听器和面向Web的应用程序上下文初始化IoC容器。

  • Web-MVC模块包含用于Web应用程序的Spring的模型 - 视图 - 控制器(MVC)实现。

  • Web-Socket模块为Web应用程序中客户端和服务器之间基于WebSocket的双向通信提供支持。

  • Web-Portlet模块提供了在portlet环境中使用的MVC实现,并镜像了Web-Servlet模块的功能。

杂项(Miscellaneous)

其他重要的模块很少,如AOP,Aspects,Instrumentation,Web和Test模块,其详细信息如下 -

  • AOP模块提供了面向方面的编程实现,允许您定义方法拦截器和切入点,以便干净地解耦实现应该分离的功能的代码。

  • Aspects模块提供与AspectJ的集成,后者又是一个功能强大且成熟的AOP框架。

  • Instrumentation模块提供了在某些应用程序服务器中使用的类检测支持和类加载器实现。

  • Messaging模块为STOMP提供支持,作为在应用程序中使用的WebSocket子协议。 它还支持用于从WebSocket客户端路由和处理STOMP消息的注释编程模型。

  • Test模块支持使用JUnit或TestNG框架测试Spring组件。

Spring - Environment Setup

本章将指导您如何准备开发环境以开始使用Spring Framework。 它还将教您如何在设置Spring Framework之前在您的机器上设置JDK,Tomcat和Eclipse -

第1步 - 安装Java开发工具包(JDK)

您可以从Oracle的Java站点下载最新版本的SDK - Java SE Downloads。 您将找到有关在下载文件中安装JDK的说明,请按照给出的说明安装和配置设置。 最后设置PATH和JAVA_HOME环境变量来引用包含java和javac的目录,通常分别是java_install_dir/bin和java_install_dir。

如果您运行的是Windows并且已在C:\_ jdk1.6.0_15中安装了JDK,则必须将以下行放在C:\autoexec.bat文件中。

set PATH=C:\jdk1.6.0_15\bin;%PATH% 
set JAVA_HOME=C:\jdk1.6.0_15 

或者,在Windows NT/2000/XP上,您必须右键单击“我的电脑”,选择“属性”→“高级”→“环境变量”。 然后,您必须更新PATH值并单击“确定”按钮。

在Unix(Solaris,Linux等)上,如果SDK安装在/usr/local/jdk1.6.0_15中并且您使用C shell,则必须将以下内容放入.cshrc文件中。

setenv PATH /usr/local/jdk1.6.0_15/bin:$PATH 
setenv JAVA_HOME /usr/local/jdk1.6.0_15 

或者,如果您使用Borland JBuilder,Eclipse,IntelliJ IDEA或Sun ONE Studio等集成开发环境(IDE),则必须编译并运行一个简单的程序,以确认IDE知道您在哪里安装了Java。 否则,您将必须执行IDE文档中给出的正确设置。

第2步 - 安装Apache Common Logging API

您可以从https://commons.apache.org/logging/下载最新版本的Apache Commons Logging API。 下载安装后,将二进制分发包解压到一个方便的位置。 例如,在Windows上的C:\commons-logging-1.1.1或Linux/Unix上的/usr/local/commons-logging-1.1.1中。 该目录将包含以下jar文件和其他支持文档等。

通用日志API

确保在此目录中正确设置CLASSPATH变量,否则在运行应用程序时将遇到问题。

第3步 - 安装Eclipse IDE

本教程中的所有示例都是使用Eclipse IDE编写的。 因此,我们建议您在计算机上安装最新版本的Eclipse。

要安装Eclipse IDE,请从https://www.eclipse.org/downloads/下载最新的Eclipse二进制文件。 下载安装后,将二进制分发包解压到一个方便的位置。 例如,在Windows上的C:\eclipse或Linux/Unix上的/ usr/local/eclipse中,最后适当地设置PATH变量。

可以通过在Windows机器上执行以下命令来启动Eclipse,或者只需双击eclipse.exe即可

%C:\eclipse\eclipse.exe 

可以通过在Unix(Solaris,Linux等)机器上执行以下命令来启动Eclipse -

$/usr/local/eclipse/eclipse

成功启动后,如果一切正常,那么它应该显示以下结果 -

Eclipse主页

第4步 - 设置Spring Framework库

现在如果一切正常,那么您可以继续设置Spring框架。 以下是在您的计算机上下载和安装框架的简单步骤。

  • 选择是否要在Windows或Unix上安装Spring,然后继续下一步下载Windows的.zip文件和Unix的.tz文件。

  • https://repo.spring.io/release/org/springframework/spring下载最新版本的Spring框架二进制文件。

  • 在开发本教程时,在Windows机器上下载了spring-framework-4.1.6.RELEASE-dist.zip 。 解压缩下载的文件后,它在E:\spring中提供以下目录结构。

春季目录

您将在目录E:\spring\libs找到所有Spring库。 确保在此目录中正确设置CLASSPATH变量,否则在运行应用程序时将遇到问题。 如果您使用的是Eclipse,则不需要设置CLASSPATH,因为所有设置都将通过Eclipse完成。

完成最后一步后,您就可以在下一章继续学习第一个Spring示例了。

Spring - Hello World Example

让我们开始使用Spring Framework进行实际编程。 在开始使用Spring框架编写第一个示例之前,必须确保已按照Spring - Environment Setup Chapter中的说明正确设置了Spring环境。 我们还假设您对Eclipse IDE有一些工作知识。

现在让我们继续编写一个简单的Spring应用程序,它将打印出“Hello World!” 或基于Spring Beans配置文件中完成的配置的任何其他消息。

第1步 - 创建Java项目

第一步是使用Eclipse IDE创建一个简单的Java项目。 按照选项File → New → Project ,最后从向导列表中选择Java Project向导。 现在使用向导窗口将项目命名为HelloSpring ,如下所示 -

你好Spring精灵

成功创建项目后,您将在Project Explorer拥有以下内容 -

Hello Spring目录

第2步 - 添加所需的库

第二步,让我们在项目中添加Spring Framework和通用日志API库。 为此,右键单击项目名称HelloSpring ,然后按照上下文菜单中的以下选项 - Build Path → Configure Build Path以显示Java构建路径窗口,如下所示 -

Java构建路径

现在使用Libraries选项卡下的Add External JARs按钮从Spring Framework和Common Logging安装目录添加以下核心JAR -

  • commons-logging-1.1.1

  • spring-aop-4.1.6.RELEASE

  • spring-aspects-4.1.6.RELEASE

  • spring-beans-4.1.6.RELEASE

  • spring-context-4.1.6.RELEASE

  • spring-context-support-4.1.6.RELEASE

  • spring-core-4.1.6.RELEASE

  • spring-expression-4.1.6.RELEASE

  • spring-instrument-4.1.6.RELEASE

  • spring-instrument-tomcat-4.1.6.RELEASE

  • spring-jdbc-4.1.6.RELEASE

  • spring-jms-4.1.6.RELEASE

  • spring-messaging-4.1.6.RELEASE

  • spring-orm-4.1.6.RELEASE

  • spring-oxm-4.1.6.RELEASE

  • spring-test-4.1.6.RELEASE

  • spring-tx-4.1.6.RELEASE

  • spring-web-4.1.6.RELEASE

  • spring-webmvc-4.1.6.RELEASE

  • spring-webmvc-portlet-4.1.6.RELEASE

  • spring-websocket-4.1.6.RELEASE

第3步 - 创建源文件

现在让我们在HelloSpring项目下创建实际的源文件。 首先,我们需要创建一个名为com.iowiki的包。 要执行此操作,请右键单击package explorer部分中的src ,然后单击选项 - New → Package

接下来,我们将在com.iowiki包下创建HelloWorld.javaMainApp.java文件。

Spring源文件

以下是HelloWorld.java文件的内容 -

package com.iowiki;
public class HelloWorld {
   private String message;
   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}

以下是第二个文件MainApp.java的内容 -

package com.iowiki;
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 obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
   }
}

关于主要计划,需要注意以下两点:

  • 第一步是创建一个应用程序上下文,我们使用框架API ClassPathXmlApplicationContext() 。 此API加载bean配置文件,并最终基于提供的API,它负责创建和初始化所有对象,即配置文件中提到的bean。

  • 第二步用于使用创建的上下文的getBean()方法获取所需的bean。 此方法使用bean ID返回一个通用对象,该对象最终可以转换为实际对象。 一旦有了对象,就可以使用该对象来调用任何类方法。

第4步 - 创建Bean配置文件

您需要创建一个Bean配置文件,该文件是一个XML文件,并充当粘合bean(即类)的粘合剂。 需要在src目录下创建此文件,如以下屏幕截图所示 -

Bean配置文件

通常,开发人员将此文件命名为Beans.xml ,但您可以选择任何您喜欢的名称。 您必须确保此文件在CLASSPATH中可用,并在创建应用程序上下文时在主应用程序中使用相同的名称,如MainApp.java文件中所示。

Beans.xml用于为不同的bean分配唯一ID,并控制具有不同值的对象的创建,而不会影响任何Spring源文件。 例如,使用以下文件可以传递“message”变量的任何值,并且可以打印不同的消息值,而不会影响HelloWorld.java和MainApp.java文件。 让我们看看它是如何工作的 -

<?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.0.xsd">
   <bean id = "helloWorld" class = "com.iowiki.HelloWorld">
      <property name = "message" value = "Hello World!"/>
   </bean>
</beans>

当Spring应用程序加载到内存中时,Framework使用上面的配置文件来创建定义的所有bean,并为它们分配《bean》标记中定义的唯一ID。 您可以使用《property》标记来传递对象创建时使用的不同变量的值。

第5步 - 运行程序

完成创建源和Bean配置文件后,您就可以完成此步骤,即编译和运行程序。 为此,请保持MainApp.Java文件选项卡处于活动状态,并使用Eclipse IDE中的Run选项或使用Ctrl + F11编译并运行MainApp应用程序。 如果您的应用程序一切正常,这将在Eclipse IDE的控制台中打印以下消息 -

Your Message : Hello World!

恭喜,您已成功创建了第一个Spring应用程序。 通过更改“message”属性的值并保持源文件不变,可以看到上述Spring应用程序的灵活性。

Spring - IoC Containers

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

容器通过读取提供的配置元数据获取有关要实例化,配置和组装的对象的指令。 配置元数据可以由XML,Java注释或Java代码表示。 下图表示Spring的工作原理的高级视图。 Spring IoC容器利用Java POJO类和配置元数据来生成完全配置和可执行的系统或应用程序。

Spring IoC Container

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

Sr.No. 容器和描述
1 Spring BeanFactory容器

这是提供DI基本支持的最简单容器,由org.springframework.beans.factory.BeanFactory接口定义。 BeanFactory和相关的接口,例如BeanFactoryAware,InitializingBean,DisposableBean,仍然存在于Spring中,目的是向后兼容与Spring集成的大量第三方框架。

2 Spring ApplicationContext容器

此容器添加了更多特定于企业的功能,例如从属性文件解析文本消息的功能以及将应用程序事件发布到感兴趣的事件侦听器的功能。 此容器由org.springframework.context.ApplicationContext接口定义。

ApplicationContext容器包含BeanFactory容器的所有功能,因此通常建议使用BeanFactory 。 BeanFactory仍可用于轻量级应用程序,如移动设备或基于applet的应用程序,其中数据量和速度都很重要。

Spring - Bean Definition

构成应用程序主干并由Spring IoC容器管理的对象称为beans 。 bean是一个由Spring IoC容器实例化,组装和管理的对象。 这些bean是使用您提供给容器的配置元数据创建的。 例如,以前面章节中已经看到的XML“bean /”定义的形式。

Bean定义包含称为configuration metadata的信息,容器需要知道以下内容 -

  • 如何创建一个bean
  • Bean的生命周期细节
  • Bean的依赖关系

所有上述配置元数据都转换为构成每个bean定义的以下属性集。

Sr.No. 属性和描述
1

class

此属性是必需的,并指定用于创建bean的bean类。

2

name

此属性唯一地指定bean标识符。 在基于XML的配置元数据中,您使用id和/或name属性来指定bean标识符。

3

scope

此属性指定从特定bean定义创建的对象的范围,将在bean范围章节中讨论。

4

constructor-arg

这用于注入依赖项,将在后续章节中讨论。

5

properties

这用于注入依赖项,将在后续章节中讨论。

6

autowiring mode

这用于注入依赖项,将在后续章节中讨论。

7

lazy-initialization mode

延迟初始化的bean告诉IoC容器在第一次请求时创建bean实例,而不是在启动时创建。

8

initialization method

在容器设置了bean之后所有必要属性之后调用的回调。 它将在bean生命周期章节中讨论。

9

destruction method

当包含bean的容器被销毁时使用的回调。 它将在bean生命周期章节中讨论。

Spring配置元数据

Spring IoC容器与实际编写此配置元数据的格式完全分离。 以下是为Spring容器提供配置元数据的三种重要方法 -

  • 基于XML的配置文件。
  • 基于注释的配置
  • 基于Java的配置

您已经了解了如何向容器提供基于XML的配置元数据,但让我们看一下基于XML的配置文件的另一个示例,其中包含不同的bean定义,包括延迟初始化,初始化方法和销毁方法 -

<?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.0.xsd">
   <!-- A simple bean definition -->
   <bean id = "..." class = "...">
      <!-- collaborators and configuration for this bean go here -->
   </bean>
   <!-- A bean definition with lazy init set on -->
   <bean id = "..." class = "..." lazy-init = "true">
      <!-- collaborators and configuration for this bean go here -->
   </bean>
   <!-- A bean definition with initialization method -->
   <bean id = "..." class = "..." init-method = "...">
      <!-- collaborators and configuration for this bean go here -->
   </bean>
   <!-- A bean definition with destruction method -->
   <bean id = "..." class = "..." destroy-method = "...">
      <!-- collaborators and configuration for this bean go here -->
   </bean>
   <!-- more bean definitions go here -->
</beans>

您可以查看Spring Hello World示例以了解如何定义,配置和创建Spring Beans。

我们将在单独的章节中讨论基于注释的配置。 在开始使用带有Annotations的Spring Dependency Injection进行编程之前,我们希望您在一个单独的章节中讨论它,因为我们希望您掌握一些其他重要的Spring概念。

Spring - Bean Scopes

定义时,您可以选择声明该bean的作用域。 例如,要在每次需要时强制Spring生成一个新的bean实例,您应该将bean的scope属性声明为prototype 。 类似地,如果您希望Spring在每次需要时返回相同的bean实例,则应将bean的scope属性声明为singleton

Spring Framework支持以下五个范围,其中三个范围仅在您使用支持Web的ApplicationContext时才可用。

Sr.No. 范围和描述
1

singleton

这将bean定义范围限定为每个Spring IoC容器的单个实例(默认)。

2

prototype

这将单个bean定义范围限定为具有任意数量的对象实例。

3

request

这将bean定义范围限定为HTTP请求。 仅在Web感知Spring ApplicationContext的上下文中有效。

4

session

这将bean定义范围限定为HTTP会话。 仅在Web感知Spring ApplicationContext的上下文中有效。
5

global-session

这将bean定义范围限定为全局HTTP会话。 仅在Web感知Spring ApplicationContext的上下文中有效。

在本章中,我们将讨论前两个范围,其余三个将在讨论Web感知Spring ApplicationContext时进行讨论。

单身范围

如果范围设置为singleton,则Spring IoC容器只创建该bean定义定义的对象的一个​​实例。 此单个实例存储在此类单例bean的缓存中,并且该命名Bean的所有后续请求和引用都将返回缓存对象。

默认范围始终为singleton。 但是,当您需要一个且只有一个bean实例时,可以在bean配置文件中将scope属性设置为singleton ,如以下代码段所示 -

<!-- A bean definition with singleton scope -->
<bean id = "..." class = "..." scope = "singleton">
   <!-- collaborators and configuration for this bean go here -->
</bean>

例子 (Example)

让我们有一个可用的Eclipse IDE,并按照以下步骤创建一个Spring应用程序 -

脚步 描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3com.iowiki包下创建Java类HelloWorldMainApp
4src文件夹下创建Beans配置文件Beans.xml
5 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

以下是HelloWorld.java文件的内容 -

package com.iowiki;
public class HelloWorld {
   private String message;
   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}

以下是MainApp.java文件的内容 -

package com.iowiki;
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.setMessage("I'm object A");
      objA.getMessage();
      HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
      objB.getMessage();
   }
}

以下是单例范围所需的配置文件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.0.xsd">
   <bean id = "helloWorld" class = "com.iowiki.HelloWorld" scope = "singleton">
   </bean>
</beans>

完成源和bean配置文件的创建后,让我们运行应用程序。 如果您的应用程序一切正常,它将打印以下消息 -

Your Message : I'm object A
Your Message : I'm object A

原型范围

如果范围设置为prototype,则每次对该特定bean发出请求时,Spring IoC容器都会创建该对象的新bean实例。 通常,对所有state-full bean使用原型范围,对无状态bean使用singleton范围。

要定义原型范围,可以在bean配置文件中将scope属性设置为prototype ,如以下代码段所示 -

<!-- A bean definition with prototype scope -->
<bean id = "..." class = "..." scope = "prototype">
   <!-- collaborators and configuration for this bean go here -->
</bean>

例子 (Example)

让我们使用Eclipse IDE并按照以下步骤创建Spring应用程序 -

脚步 描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3com.iowiki包下创建Java类HelloWorldMainApp
4src文件夹下创建Beans配置文件Beans.xml
5 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

这是HelloWorld.java文件的内容

package com.iowiki;
public class HelloWorld {
   private String message;
   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}

以下是MainApp.java文件的内容 -

package com.iowiki;
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.setMessage("I'm object A");
      objA.getMessage();
      HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
      objB.getMessage();
   }
}

以下是原型范围所需的配置文件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.0.xsd">
   <bean id = "helloWorld" class = "com.iowiki.HelloWorld" scope = "prototype">
   </bean>
</beans>

完成源和bean配置文件的创建后,让我们运行应用程序。 如果您的应用程序一切正常,它将打印以下消息 -

Your Message : I'm object A
Your Message : null

Spring - Bean Life Cycle

Spring bean的生命周期很容易理解。 当bean被实例化时,可能需要执行一些初始化以使其进入可用状态。 类似地,当不再需要bean并从容器中移除bean时,可能需要进行一些清理。

虽然,在bean实例化及其销毁之间存在幕后发生的活动列表,但本章仅讨论两个重要的bean生命周期回调方法,这些方法在bean初始化及其销毁时是必需的。

要定义bean的设置和拆卸,我们只需使用initmethod和/或destroy-method参数声明<bean>。 init-method属性指定在实例化时立即在bean上调用的方法。 类似地,destroymethod指定在从容器中删除bean之前调用的方法。

初始化回调

org.springframework.beans.factory.InitializingBean接口指定一个方法 -

void afterPropertiesSet() throws Exception;

这样,你可以简单地实现上面的接口和初始化工作,可以在afterPropertiesSet()方法里面完成如下 -

public class ExampleBean implements InitializingBean {
   public void afterPropertiesSet() {
      // do some initialization work
   }
}

对于基于XML的配置元数据,可以使用init-method属性指定具有void无参数签名的方法的名称。 例如 -

<bean id = "exampleBean" class = "examples.ExampleBean" init-method = "init"/>

以下是类定义 -

public class ExampleBean {
   public void init() {
      // do some initialization work
   }
}

销毁回调

org.springframework.beans.factory.DisposableBean接口指定一个方法 -

void destroy() throws Exception;

这样,你可以简单地实现上面的接口和完成工作,可以在destroy()方法里面完成如下 -

public class ExampleBean implements DisposableBean {
   public void destroy() {
      // do some destruction work
   }
}

对于基于XML的配置元数据,可以使用destroy-method属性指定具有void无参数签名的方法的名称。 例如 -

<bean id = "exampleBean" class = "examples.ExampleBean" destroy-method = "destroy"/>

以下是类定义 -

public class ExampleBean {
   public void destroy() {
      // do some destruction work
   }
}

如果您在非Web应用程序环境中使用Spring的IoC容器; 例如,在富客户端桌面环境中,您使用JVM注册关闭挂钩。 这样做可确保正常关闭并在单例bean上调用相关的destroy方法,以便释放所有资源。

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

例子 (Example)

让我们有一个可用的Eclipse IDE,并按照以下步骤创建一个Spring应用程序 -

脚步 描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3com.iowiki包下创建Java类HelloWorldMainApp
4src文件夹下创建Beans配置文件Beans.xml
5 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

以下是HelloWorld.java文件的内容 -

package com.iowiki;
public class HelloWorld {
   private String message;
   public void setMessage(String message){
      this.message = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
   public void init(){
      System.out.println("Bean is going through init.");
   }
   public void destroy() {
      System.out.println("Bean will destroy now.");
   }
}

以下是MainApp.java文件的内容。 在这里,您需要注册在AbstractApplicationContext类上声明的关闭钩子registerShutdownHook()方法。 这将确保正常关闭并调用相关的销毁方法。

package com.iowiki;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
   public static void main(String[] args) {
      AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
      context.registerShutdownHook();
   }
}

以下是init和destroy方法所需的配置文件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.0.xsd">
   <bean id = "helloWorld" class = "com.iowiki.HelloWorld" init-method = "init" 
      destroy-method = "destroy">
      <property name = "message" value = "Hello World!"/>
   </bean>
</beans>

完成源和bean配置文件的创建后,让我们运行应用程序。 如果您的应用程序一切正常,它将打印以下消息 -

Bean is going through init.
Your Message : Hello World!
Bean will destroy now.

默认初始化和销毁​​方法

如果你有太多的bean具有相同名称的初始化和/或销毁方法,则不需要在每个单独的bean上声明init-methoddestroy-method 。 相反,框架提供了使用“beans”元素上的default-init-methoddefault-destroy-method属性配置此类情况的灵活性,如下所示 -

<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.0.xsd"
   default-init-method = "init" 
   default-destroy-method = "destroy">
   <bean id = "..." class = "...">
      <!-- collaborators and configuration for this bean go here -->
   </bean>
</beans>

Spring - Bean Post Processors

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

您可以配置多个BeanPostProcessor接口,并且您可以通过设置order属性来控制这些BeanPostProcessor接口的执行order前提是BeanPostProcessor实现了Ordered接口。

BeanPostProcessors在bean(或对象)实例上运行,这意味着Spring IoC容器实例化一个bean实例,然后BeanPostProcessor接口完成它们的工作。

ApplicationContext自动检测使用BeanPostProcessor接口的实现定义的任何bean,并将这些bean注册为后处理器,然后在创建bean时由容器适当调用。

例子 (Example)

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

让我们有一个可用的Eclipse IDE,并按照以下步骤创建一个Spring应用程序 -

脚步 描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3com.iowiki包下创建Java类HelloWorldInitHelloWorldMainApp
4src文件夹下创建Beans配置文件Beans.xml
5 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

以下是HelloWorld.java文件的内容 -

package com.iowiki;
public class HelloWorld {
   private String message;
   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
   public void init(){
      System.out.println("Bean is going through init.");
   }
   public void destroy(){
      System.out.println("Bean will destroy now.");
   }
}

这是实现BeanPostProcessor的一个非常基本的例子,它在任何bean初始化之前和之后打印bean名称。 您可以在初始化bean之前和之后实现更复杂的逻辑,因为您可以访问后处理器方法中的bean对象。

以下是InitHelloWorld.java文件的内容 -

package com.iowiki;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InitHelloWorld implements BeanPostProcessor {
   public Object postProcessBeforeInitialization(Object bean, String beanName) 
      throws BeansException {
      System.out.println("BeforeInitialization : " + beanName);
      return bean;  // you can return any other object as well
   }
   public Object postProcessAfterInitialization(Object bean, String beanName) 
      throws BeansException {
      System.out.println("AfterInitialization : " + beanName);
      return bean;  // you can return any other object as well
   }
}

以下是MainApp.java文件的内容。 在这里,您需要注册在AbstractApplicationContext类上声明的关闭钩子registerShutdownHook()方法。 这将确保正常关闭并调用相关的销毁方法。

package com.iowiki;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
   public static void main(String[] args) {
      AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
      context.registerShutdownHook();
   }
}

以下是init和destroy方法所需的配置文件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.0.xsd">
   <bean id = "helloWorld" class = "com.iowiki.HelloWorld"
      init-method = "init" destroy-method = "destroy">
      <property name = "message" value = "Hello World!"/>
   </bean>
   <bean class = "com.iowiki.InitHelloWorld" />
</beans>

完成创建源和bean配置文件后,让我们运行应用程序。 如果您的应用程序一切正常,它将打印以下消息 -

BeforeInitialization : helloWorld
Bean is going through init.
AfterInitialization : helloWorld
Your Message : Hello World!
Bean will destroy now.

Spring - Bean Definition Inheritance

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

子bean定义从父定义继承配置数据。 子定义可以根据需要覆盖某些值或添加其他值。

Spring Bean定义继承与Java类继承无关,但继承概念是相同的。 您可以将父bean定义定义为模板,其他子bean可以从父bean继承所需的配置。

使用基于XML的配置元数据时,可以使用parent属性指定子bean定义,并将父bean指定为此属性的值。

例子 (Example)

让我们有一个可用的Eclipse IDE,并按照以下步骤创建一个Spring应用程序 -

脚步 描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3com.iowiki包下创建Java类HelloWorldHelloIndiaMainApp
4src文件夹下创建Beans配置文件Beans.xml
5 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

以下是配置文件Beans.xml ,我们在其中定义了“helloWorld”bean,它有两个属性message1message1 。 接下来,通过使用parent属性将“helloIndia”bean定义为“helloWorld”bean的parent 。 子bean按原样继承message1属性,并覆盖message1属性并引入另一个属性message3

<?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.0.xsd">
   <bean id = "helloWorld" class = "com.iowiki.HelloWorld">
      <property name = "message1" value = "Hello World!"/>
      <property name = "message2" value = "Hello Second World!"/>
   </bean>
   <bean id ="helloIndia" class = "com.iowiki.HelloIndia" parent = "helloWorld">
      <property name = "message1" value = "Hello India!"/>
      <property name = "message3" value = "Namaste India!"/>
   </bean>
</beans>

以下是HelloWorld.java文件的内容 -

package com.iowiki;
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.iowiki;
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.iowiki;
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 Definition Inheritance而传递了它。

豆定义模板

您可以创建Bean定义模板,该模板可供其他子bean定义使用,而无需花费太多精力。 在定义Bean定义模板时,不应指定class属性并应指定abstract属性,并应指定值为true的abstract属性,如以下代码段所示 -

<?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.0.xsd">
   <bean id = "beanTeamplate" abstract = "true">
      <property name = "message1" value = "Hello World!"/>
      <property name = "message2" value = "Hello Second World!"/>
      <property name = "message3" value = "Namaste India!"/>
   </bean>
   <bean id = "helloIndia" class = "com.iowiki.HelloIndia" parent = "beanTeamplate">
      <property name = "message1" value = "Hello India!"/>
      <property name = "message3" value = "Namaste India!"/>
   </bean>
</beans>

父bean不能单独实例化,因为它不完整,并且也明确标记为abstract 。 当定义是这样的抽象时,它只能用作纯模板bean定义,用作子定义的父定义。

Spring - Dependency Injection

每个基于Java的应用程序都有一些对象可以协同工作,以呈现最终用户所看到的工作应用程序。 在编写复杂的Java应用程序时,应用程序类应尽可能独立于其他Java类,以增加重用这些类的可能性,并在单元测试时独立于其他类测试它们。 依赖注入(或称为布线)有助于将这些类粘合在一起,同时保持它们独立。

假设您有一个具有文本编辑器组件的应用程序,并且您想要提供拼写检查。 您的标准代码看起来像这样 -

public class TextEditor {
   private SpellChecker spellChecker;
   public TextEditor() {
      spellChecker = new SpellChecker();
   }
}

我们在这里做的是,在TextEditor和SpellChecker之间创建依赖关系。 在控制场景的反转中,我们会做这样的事情 -

public class TextEditor {
   private SpellChecker spellChecker;
   public TextEditor(SpellChecker spellChecker) {
      this.spellChecker = spellChecker;
   }
}

在这里,TextEditor不应该担心SpellChecker的实现。 SpellChecker将独立实现,并在TextEditor实例化时提供给TextEditor。 整个过程由Spring Framework控制。

在这里,我们已经从TextEditor中删除了总控制并将其保存在其他地方(即XML配置文件),并且通过Class Constructor将依赖项(即类SpellChecker)注入到TextEditor Class Constructor 。 因此,控制流已经被依赖注入(DI)“反转”,因为您已经有效地将依赖性委托给某些外部系统。

注入依赖的第二种方法是通过TextEditor类的Setter Methods ,我们将在其中创建一个SpellChecker实例。 此实例将用于调用setter方法以初始化TextEditor的属性。

因此,DI存在两个主要变体,以下两个子章节将通过示例涵盖它们 -

Sr.No. 依赖注入类型和描述
1 基于构造函数的依赖注入

当容器调用具有许多参数的类构造函数时,完成基于构造函数的DI,每个参数表示对另一个类的依赖。

2 基于Setter的依赖注入

基于setter的DI是在调用无参数构造函数或无参数静态工厂方法来实例化bean之后,通过容器调用bean上的setter方法来完成的。

您可以混合使用基于构造函数和基于Setter的DI,但使用构造函数参数作为必需依赖项和使用可选依赖项的setter是一个很好的经验法则。

使用DI原理的代码更清晰,当对象提供其依赖项时,解耦更有效。 该对象不查找其依赖项,也不知道依赖项的位置或类,而是Spring框架对所有内容都进行了处理。

Spring - Injecting Inner Beans

如您所知,Java内部类是在其他类的范围内定义的,类似地, inner beans是在另一个bean的范围内定义的bean。 因此,“property /”或“constructor-arg /”元素中的“bean /”元素称为内部bean,如下所示。

<?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.0.xsd">
   <bean id = "outerBean" class = "...">
      <property name = "target">
         <bean id = "innerBean" class = "..."/>
      </property>
   </bean>
</beans>

例子 (Example)

让我们使用Eclipse IDE并按照以下步骤创建Spring应用程序 -

脚步 描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3com.iowiki包下创建Java类TextEditorMainAppMainApp
4src文件夹下创建Beans配置文件Beans.xml
5 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

这是TextEditor.java文件的内容 -

package com.iowiki;
public class TextEditor {
   private SpellChecker spellChecker;
   // a setter method to inject the dependency.
   public void setSpellChecker(SpellChecker spellChecker) {
      System.out.println("Inside setSpellChecker." );
      this.spellChecker = spellChecker;
   }
   // a getter method to return spellChecker
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

以下是另一个依赖类文件SpellChecker.java -

package com.iowiki;
public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling(){
      System.out.println("Inside checkSpelling." );
   }
}

以下是MainApp.java文件的内容 -

package com.iowiki;
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");
      TextEditor te = (TextEditor) context.getBean("textEditor");
      te.spellCheck();
   }
}

以下是配置文件Beans.xml ,它具有基于setter的注入配置,但使用inner beans -

<?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.0.xsd">
   <!-- Definition for textEditor bean using inner bean -->
   <bean id = "textEditor" class = "com.iowiki.TextEditor">
      <property name = "spellChecker">
         <bean id = "spellChecker" class = "com.iowiki.SpellChecker"/>
      </property>
   </bean>
</beans>

完成源和bean配置文件的创建后,让我们运行应用程序。 如果您的应用程序一切正常,它将打印以下消息 -

Inside SpellChecker constructor.
Inside setSpellChecker.
Inside checkSpelling.

Spring - Injecting Collection

您已经了解了如何使用Bean配置文件中“property”标记的ref属性使用value属性和对象引用来配置原始数据类型。 这两种情况都涉及将奇异值传递给bean。

现在,如果要传递多个值,如List Collection类型,如List,Set,Map和Properties,该怎么办? 为了处理这种情况,Spring提供了四种类型的集合配置元素,如下所示 -

Sr.No 元素和描述
1

《list》

这有助于布线,即注入值列表,允许重复。

2

《set》

这有助于连接一组值,但没有任何重复。

3

《map》

这可以用于注入名称 - 值对的集合,其中name和value可以是任何类型。

4

《props》

这可以用于注入名称 - 值对的集合,其中名称和值都是字符串。

您可以使用来连接java.util.Collection或array任何实现。

您将遇到两种情况(a)传递集合的直接值和(b)将bean的引用作为集合元素之一传递。

例子 (Example)

让我们有一个可用的Eclipse IDE,并按照以下步骤创建一个Spring应用程序 -

脚步 描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3com.iowiki包下创建Java类MainAppMainApp
4src文件夹下创建Beans配置文件Beans.xml
5 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

这是JavaCollection.java文件的内容 -

package com.iowiki;
import java.util.*;
public class JavaCollection {
   List addressList;
   Set  addressSet;
   Map  addressMap;
   Properties addressProp;
   // a setter method to set List
   public void setAddressList(List addressList) {
      this.addressList = addressList;
   }
   // prints and returns all the elements of the list.
   public List getAddressList() {
      System.out.println("List Elements :"  + addressList);
      return addressList;
   }
   // a setter method to set Set
   public void setAddressSet(Set addressSet) {
      this.addressSet = addressSet;
   }
   // prints and returns all the elements of the Set.
   public Set getAddressSet() {
      System.out.println("Set Elements :"  + addressSet);
      return addressSet;
   }
   // a setter method to set Map
   public void setAddressMap(Map addressMap) {
      this.addressMap = addressMap;
   }
   // prints and returns all the elements of the Map.
   public Map getAddressMap() {
      System.out.println("Map Elements :"  + addressMap);
      return addressMap;
   }
   // a setter method to set Property
   public void setAddressProp(Properties addressProp) {
      this.addressProp = addressProp;
   }
   // prints and returns all the elements of the Property.
   public Properties getAddressProp() {
      System.out.println("Property Elements :"  + addressProp);
      return addressProp;
   }
}

以下是MainApp.java文件的内容 -

package com.iowiki;
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");
      JavaCollection jc=(JavaCollection)context.getBean("javaCollection");
      jc.getAddressList();
      jc.getAddressSet();
      jc.getAddressMap();
      jc.getAddressProp();
   }
}

以下是配置文件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.0.xsd">
   <!-- Definition for javaCollection -->
   <bean id = "javaCollection" class = "com.iowiki.JavaCollection">
      <!-- results in a setAddressList(java.util.List) call -->
      <property name = "addressList">
         <list>
            <value>INDIA</value>
            <value>Pakistan</value>
            <value>USA</value>
            <value>USA</value>
         </list>
      </property>
      <!-- results in a setAddressSet(java.util.Set) call -->
      <property name = "addressSet">
         <set>
            <value>INDIA</value>
            <value>Pakistan</value>
            <value>USA</value>
            <value>USA</value>
         </set>
      </property>
      <!-- results in a setAddressMap(java.util.Map) call -->
      <property name = "addressMap">
         <map>
            <entry key = "1" value = "INDIA"/>
            <entry key = "2" value = "Pakistan"/>
            <entry key = "3" value = "USA"/>
            <entry key = "4" value = "USA"/>
         </map>
      </property>
      <!-- results in a setAddressProp(java.util.Properties) call -->
      <property name = "addressProp">
         <props>
            <prop key = "one">INDIA</prop>
            <prop key = "one">INDIA</prop>
            <prop key = "two">Pakistan</prop>
            <prop key = "three">USA</prop>
            <prop key = "four">USA</prop>
         </props>
      </property>
   </bean>
</beans>

完成源和bean配置文件的创建后,让我们运行应用程序。 如果您的应用程序一切正常,它将打印以下消息 -

List Elements :[INDIA, Pakistan, USA, USA] 
Set Elements :[INDIA, Pakistan, USA] 
ap Elements :{1 = INDIA, 2 = Pakistan, 3 = USA, 4 = USA} 
Property Elements :{two = Pakistan, one = INDIA, three = USA, four = USA} 

注入Bean引用

以下Bean定义将帮助您了解如何将bean引用注入为集合的元素之一。 即使你可以将引用和值混合在一起,如下面的代码片段所示 -

<?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.0.xsd">
   <!-- Bean Definition to handle references and values -->
   <bean id = "..." class = "...">
      <!-- Passing bean reference  for java.util.List -->
      <property name = "addressList">
         <list>
            <ref bean = "address1"/>
            <ref bean = "address2"/>
            <value>Pakistan</value>
         </list>
      </property>
      <!-- Passing bean reference  for java.util.Set -->
      <property name = "addressSet">
         <set>
            <ref bean = "address1"/>
            <ref bean = "address2"/>
            <value>Pakistan</value>
         </set>
      </property>
      <!-- Passing bean reference  for java.util.Map -->
      <property name = "addressMap">
         <map>
            <entry key = "one" value = "INDIA"/>
            <entry key = "two" value-ref = "address1"/>
            <entry key = "three" value-ref = "address2"/>
         </map>
      </property>
   </bean>
</beans>

要使用上面的bean定义,您需要以这样的方式定义setter方法,使它们也能够处理引用。

注入null和空字符串值

如果您需要将空字符串作为值传递,那么您可以按如下方式传递它 -

<bean id = "..." class = "exampleBean">
   <property name = "email" value = ""/>
</bean>

前面的示例等同于Java代码:exampleBean.setEmail(“”)

如果需要传递NULL值,则可以按如下方式传递 -

<bean id = "..." class = "exampleBean">
   <property name = "email"><null/></property>
</bean>

前面的示例等同于Java代码:exampleBean.setEmail(null)

Spring - Beans Auto-Wiring

您已经学习了如何使用元素声明bean,并使用XML配置文件中的元素注入

Spring容器可以在不使用“constructor-arg”和“property”元素的情况下autowire连接协作bean之间的关系,这有助于减少为大型基于Spring的应用程序编写的XML配置量。

自动装配模式

以下是自动装配模式,可用于指示Spring容器使用自动装配进行依赖注入。 您可以使用元素的autowire属性为bean定义指定autowire模式。

Sr.No 模式和说明
1 no

这是默认设置,这意味着没有自动装配,您应该使用显式bean引用进行连接。 你对这种布线没什么特别的。 这是您在依赖注入章节中已经看到的内容。

2 byName

按属性名称自动装配。 Spring容器在XML配置文件中byName autowire属性设置为byName autowire属性。 然后,它尝试匹配并将其属性与配置文件中由相同名称定义的bean相连。

3 byType

按属性数据类型自动装配。 Spring容器在XML配置文件中查看autowire属性设置为byType autowire属性。 然后,如果属性的type与配置文件中的一个bean名称匹配,则会尝试匹配并连接属性。 如果存在多个这样的bean,则抛出致命异常。

4 constructor

与byType类似,但type适用于构造函数参数。 如果容器中没有构造函数参数类型的一个bean,则会引发致命错误。

5 autodetect

Spring首先尝试通过constructor使用autowire连接,如果它不起作用,Spring会尝试通过byType自动装配。

您可以使用byTypeconstructor自动装配模式连接数组和其他类型集合。

自动装配的限制

自动装配在项目中一致使用时效果最佳。 如果一般不使用自动装配,那么开发人员使用它来连接一个或两个bean定义可能会让人感到困惑。 但是,自动装配可以显着减少指定属性或构造函数参数的需要,但在使用之前应考虑自动装配的限制和缺点。

Sr.No. 限制和描述
1

Overriding possibility

您仍然可以使用设置指定依赖项,这些设置将始终覆盖自动装配。

2

Primitive data types

您无法自动装配所谓的简单属性,例如基元,字符串和类。

3

Confusing nature

自动装配不如显式布线精确,因此如果可能,请使用明确的布线。

Spring - Annotation Based Configuration

从Spring 2.5开始,可以使用annotations配置依赖注入。 因此,不是使用XML来描述bean连接,而是可以通过在相关的类,方法或字段声明上使用注释将bean配置移动到组件类本身。

在注入XML之前执行注释注入。 因此,对于通过两种方法连接的属性,后一种配置将覆盖前者。

默认情况下,Spring容器中未打开注释接线。 因此,在我们使用基于注释的布线之前,我们需要在Spring配置文件中启用它。 因此,如果要在Spring应用程序中使用任何注释,请考虑以下配置文件。

<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context = "http://www.springframework.org/schema/context"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context-3.0.xsd">
   <context:annotation-config/>
   <!-- bean definitions go here -->
</beans>

一旦配置了,就可以开始注释代码,以指示Spring应该自动将值连接到属性,方法和构造函数中。 让我们看一些重要的注释来理解它们是如何工作的 -

Sr.No. 注释和说明
1 @Required

@Required注释适用于bean属性setter方法。

2 @Autowired

@Autowired注释可以应用于bean属性setter方法,非setter方法,构造函数和属性。

3 @Qualifier

@Qualifier注释和@Autowired可用于通过指定将连接哪个确切的bean来消除混淆。

4 JSR-250注释

Spring支持基于JSR-250的注释,包括@ Resource,@ PostConstruct和@PreDestroy注释。

Spring - Java Based Configuration

到目前为止,您已经了解了我们如何使用XML配置文件配置Spring bean。 如果您对XML配置感到满意,那么实际上不需要了解如何继续使用基于Java的配置,因为您将使用任一可用配置获得相同的结果。

基于Java的配置选项使您可以在没有XML的情况下编写大部分Spring配置,但是在本章中介绍的几个基于Java的注释的帮助下。

@Configuration&@Bean Annotations

使用@Configuration注释类表示Spring IoC容器可以将该类用作bean定义的源。 @Bean注释告诉Spring,使用@Bean注释的方法将返回一个应该在Spring应用程序上下文中注册为bean的对象。 最简单的@Configuration类如下 -

package com.iowiki;
import org.springframework.context.annotation.*;
@Configuration
public class HelloWorldConfig {
   @Bean 
   public HelloWorld helloWorld(){
      return new HelloWorld();
   }
}

上面的代码将等同于以下XML配置 -

<beans>
   <bean id = "helloWorld" class = "com.iowiki.HelloWorld" />
</beans>

这里,方法名称用@Bean注释作为bean ID,它创建并返回实际的bean。 您的配置类可以具有多个@Bean的声明。 一旦定义了配置类,就可以使用AnnotationConfigApplicationContext加载并将它们提供给Spring容器,如下所示 -

public static void main(String[] args) {
   ApplicationContext ctx = new AnnotationConfigApplicationContext(HelloWorldConfig.class);
   HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
   helloWorld.setMessage("Hello World!");
   helloWorld.getMessage();
}

您可以加载各种配置类,如下所示 -

public static void main(String[] args) {
   AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
   ctx.register(AppConfig.class, OtherConfig.class);
   ctx.register(AdditionalConfig.class);
   ctx.refresh();
   MyService myService = ctx.getBean(MyService.class);
   myService.doStuff();
}

例子 (Example)

让我们有一个可用的Eclipse IDE,并按照以下步骤创建一个Spring应用程序 -

脚步 描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3 因为您使用的是基于Java的注释,所以您还需要从Java安装目录和ASM.jar库中添加CGLIB.jarASM.jar库可以从asm.ow2.org下载。
4com.iowiki包下创建Java类HelloWorldConfigHelloWorldMainApp
5 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

这是HelloWorldConfig.java文件的内容

package com.iowiki;
import org.springframework.context.annotation.*;
@Configuration
public class HelloWorldConfig {
   @Bean 
   public HelloWorld helloWorld(){
      return new HelloWorld();
   }
}

这是HelloWorld.java文件的内容

package com.iowiki;
public class HelloWorld {
   private String message;
   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}

以下是MainApp.java文件的内容

package com.iowiki;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;
public class MainApp {
   public static void main(String[] args) {
      ApplicationContext ctx = 
         new AnnotationConfigApplicationContext(HelloWorldConfig.class);
      HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
      helloWorld.setMessage("Hello World!");
      helloWorld.getMessage();
   }
}

完成所有源文件的创建并添加所需的其他库后,让我们运行该应用程序。 您应该注意,不需要配置文件。 如果您的应用程序一切正常,它将打印以下消息 -

Your Message : Hello World!

注入Bean依赖项

当@Beans彼此依赖时,表示依赖关系就像让一个bean方法调用另一个bean方法一样简单,如下所示 -

package com.iowiki;
import org.springframework.context.annotation.*;
@Configuration
public class AppConfig {
   @Bean
   public Foo foo() {
      return new Foo(bar());
   }
   @Bean
   public Bar bar() {
      return new Bar();
   }
}

这里,foo bean通过构造函数注入接收对bar的引用。 现在让我们看看另一个工作示例。

例子 (Example)

让我们有一个可用的Eclipse IDE,并按照以下步骤创建一个Spring应用程序 -

脚步 描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3 因为您使用的是基于Java的注释,所以您还需要从Java安装目录和ASM.jar库中添加CGLIB.jarASM.jar库可以从asm.ow2.org下载。
4com.iowiki包下创建Java类TextEditorConfigTextEditorMainAppMainApp
5 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

这是TextEditorConfig.java文件的内容

package com.iowiki;
import org.springframework.context.annotation.*;
@Configuration
public class TextEditorConfig {
   @Bean 
   public TextEditor textEditor(){
      return new TextEditor( spellChecker() );
   }
   @Bean 
   public SpellChecker spellChecker(){
      return new SpellChecker( );
   }
}

这是TextEditor.java文件的内容

package com.iowiki;
public class TextEditor {
   private SpellChecker spellChecker;
   public TextEditor(SpellChecker spellChecker){
      System.out.println("Inside TextEditor constructor." );
      this.spellChecker = spellChecker;
   }
   public void spellCheck(){
      spellChecker.checkSpelling();
   }
}

以下是另一个依赖类文件SpellChecker.java

package com.iowiki;
public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling(){
      System.out.println("Inside checkSpelling." );
   }
}

以下是MainApp.java文件的内容

package com.iowiki;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;
public class MainApp {
   public static void main(String[] args) {
      ApplicationContext ctx = 
         new AnnotationConfigApplicationContext(TextEditorConfig.class);
      TextEditor te = ctx.getBean(TextEditor.class);
      te.spellCheck();
   }
}

完成所有源文件的创建并添加所需的其他库后,让我们运行该应用程序。 您应该注意,不需要配置文件。 如果您的应用程序一切正常,它将打印以下消息 -

Inside SpellChecker constructor.
Inside TextEditor constructor.
Inside checkSpelling.

@Import注释

@Import注释允许从另一个配置类加载@Bean定义。 考虑如下ConfigA类 -

@Configuration
public class ConfigA {
   @Bean
   public A a() {
      return new A(); 
   }
}

您可以在另一个Bean声明中导入以上Bean声明,如下所示 -

@Configuration
@Import(ConfigA.class)
public class ConfigB {
   @Bean
   public B a() {
      return new A(); 
   }
}

现在,在实例化上下文时,不需要同时指定ConfigA.class和ConfigB.class,只需要提供ConfigB,如下所示 -

public static void main(String[] args) {
   ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
   // now both beans A and B will be available...
   A a = ctx.getBean(A.class);
   B b = ctx.getBean(B.class);
}

生命周期回调

@Bean注释支持指定任意初始化和销毁​​回调方法,就像Spring XML的init-method和bean元素上的destroy-method属性一样 -

public class Foo {
   public void init() {
      // initialization logic
   }
   public void cleanup() {
      // destruction logic
   }
}
@Configuration
public class AppConfig {
   @Bean(initMethod = "init", destroyMethod = "cleanup" )
   public Foo foo() {
      return new Foo();
   }
}

指定Bean范围

默认范围是单例,但您可以使用@Scope注释覆盖它,如下所示 -

@Configuration
public class AppConfig {
   @Bean
   @Scope("prototype")
   public Foo foo() {
      return new Foo();
   }
}

Event Handling in Spring

您已经在所有章节中看到Spring的核心是ApplicationContext ,它管理bean的完整生命周期。 ApplicationContext在加载bean时发布某些类型的事件。 例如,在启动上下文时发布ContextStoppedEvent ,在上下文停止时发布ContextStoppedEvent

ApplicationContext中的事件处理是通过ApplicationEvent类和ApplicationListener接口提供的。 因此,如果bean实现了ApplicationListener ,那么每次将ApplicationEvent发布到ApplicationContext时,都会通知该bean。

Spring提供以下标准事件 -

Sr.No. Spring内置事件和描述
1

ContextRefreshedEvent

在初始化或刷新ApplicationContext时发布此事件。 这也可以使用ConfigurableApplicationContext接口上的refresh()方法引发。

2

ContextStartedEvent

使用ConfigurableApplicationContext接口上的start()方法启动ApplicationContext时,将发布此事件。 您可以轮询数据库,也可以在收到此事件后重新启动任何已停止的应用程序。

3

ContextStoppedEvent

使用ConfigurableApplicationContext接口上的stop()方法停止ApplicationContext时,将发布此事件。 收到此活动后,您可以进行必要的保养工作。

4

ContextClosedEvent

使用ConfigurableApplicationContext接口上的close()方法关闭ApplicationContext时,将发布此事件。 封闭的环境达到其生命的终点; 它无法刷新或重新启动。

5

RequestHandledEvent

这是一个特定于Web的事件,告诉所有bean已经为HTTP请求提供服务。

Spring的事件处理是单线程的,因此如果事件被发布,除非所有接收者都收到消息,否则流程将被阻止,流程将不会继续。 因此,如果要使用事件处理,在设计应用程序时应该小心。

听取上下文事件

要监听上下文事件,bean应该实现ApplicationListener接口,该接口只有一个onApplicationEvent()方法。 因此,让我们编写一个示例来查看事件如何传播以及如何使代码根据特定事件执行所需任务。

让我们有一个可用的Eclipse IDE,并按照以下步骤创建一个Spring应用程序 -

描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3com.iowiki包下创建Java类HelloWorldCStartEventHandlerCStopEventHandlerMainApp
4src文件夹下创建Beans配置文件Beans.xml
5 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

这是HelloWorld.java文件的内容

package com.iowiki;
public class HelloWorld {
   private String message;
   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}

以下是CStartEventHandler.java文件的内容

package com.iowiki;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStartedEvent;
public class CStartEventHandler 
   implements ApplicationListener<ContextStartedEvent>{
   public void onApplicationEvent(ContextStartedEvent event) {
      System.out.println("ContextStartedEvent Received");
   }
}

以下是CStopEventHandler.java文件的内容

package com.iowiki;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStoppedEvent;
public class CStopEventHandler 
   implements ApplicationListener<ContextStoppedEvent>{
   public void onApplicationEvent(ContextStoppedEvent event) {
      System.out.println("ContextStoppedEvent Received");
   }
}

以下是MainApp.java文件的内容

package com.iowiki;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
   public static void main(String[] args) {
      ConfigurableApplicationContext context = 
         new ClassPathXmlApplicationContext("Beans.xml");
      // Let us raise a start event.
      context.start();
      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
      // Let us raise a stop event.
      context.stop();
   }
}

以下是配置文件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.0.xsd">
   <bean id = "helloWorld" class = "com.iowiki.HelloWorld">
      <property name = "message" value = "Hello World!"/>
   </bean>
   <bean id = "cStartEventHandler" class = "com.iowiki.CStartEventHandler"/>
   <bean id = "cStopEventHandler" class = "com.iowiki.CStopEventHandler"/>
</beans>

完成源和bean配置文件的创建后,让我们运行应用程序。 如果您的应用程序一切正常,它将打印以下消息 -

ContextStartedEvent Received
Your Message : Hello World!
ContextStoppedEvent Received

如果您愿意,可以发布自己的自定义事件,稍后您可以捕获相同的事件以对这些自定义事件采取任何操作。 如果您有兴趣编写自己的自定义事件,可以在Spring中查看自定义事件。

Custom Events in Spring

编写和发布您自己的自定义事件需要执行许多步骤。 按照本章中的说明编写,发布和处理Custom Spring Events。

脚步 描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki 。 所有类都将在此包下创建。
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3 通过扩展ApplicationEvent创建一个事件类CustomEvent 。 该类必须定义一个默认构造函数,该构造函数应该从ApplicationEvent类继承构造函数。
4 一旦定义了事件类,就可以从任何类发布它,让我们说实现ApplicationEventPublisherAware EventClassPublisher 。 您还需要在XML配置文件中将此类声明为bean,以便容器可以将bean标识为事件发布者,因为它实现了ApplicationEventPublisherAware接口。
5 已发布的事件可以在类中处理,让我们说EventClassHandler实现ApplicationListener接口并为自定义事件实现onApplicationEvent方法。
6src文件夹下创建bean配置文件Beans.xml ,并在MainApp类中创建Spring应用程序。
7 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

这是CustomEvent.java文件的内容

package com.iowiki;
import org.springframework.context.ApplicationEvent;
public class CustomEvent extends ApplicationEvent{
   public CustomEvent(Object source) {
      super(source);
   }
   public String toString(){
      return "My Custom Event";
   }
}

以下是CustomEventPublisher.java文件的内容

package com.iowiki;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
public class CustomEventPublisher implements ApplicationEventPublisherAware {
   private ApplicationEventPublisher publisher;
   public void setApplicationEventPublisher (ApplicationEventPublisher publisher) {
      this.publisher = publisher;
   }
   public void publish() {
      CustomEvent ce = new CustomEvent(this);
      publisher.publishEvent(ce);
   }
}

以下是CustomEventHandler.java文件的内容

package com.iowiki;
import org.springframework.context.ApplicationListener;
public class CustomEventHandler implements ApplicationListener<CustomEvent> {
   public void onApplicationEvent(CustomEvent event) {
      System.out.println(event.toString());
   }
}

以下是MainApp.java文件的内容

package com.iowiki;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
   public static void main(String[] args) {
      ConfigurableApplicationContext context = 
         new ClassPathXmlApplicationContext("Beans.xml");
      CustomEventPublisher cvp = 
         (CustomEventPublisher) context.getBean("customEventPublisher");
      cvp.publish();  
      cvp.publish();
   }
}

以下是配置文件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.0.xsd">
   <bean id = "customEventHandler" class = "com.iowiki.CustomEventHandler"/>
   <bean id = "customEventPublisher" class = "com.iowiki.CustomEventPublisher"/>
</beans>

完成源和bean配置文件的创建后,让我们运行应用程序。 如果您的应用程序一切正常,它将打印以下消息 -

y Custom Event
y Custom Event

AOP with Spring Framework

Spring Framework的一个关键组件是Aspect oriented programming (AOP)框架。 面向方面编程需要将程序逻辑分解为称为所谓关注点的不同部分。 跨越应用程序多个点的功能称为cross-cutting concerns ,这些跨领域问题在概念上与应用程序的业务逻辑分开。 有许多常见的好例子,如日志记录,审计,声明式事务,安全性,缓存等。

OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面。 依赖注入可以帮助您将应用程序对象相互分离,AOP可以帮助您将交叉问题与它们所影响的对象分离。 AOP就像Perl,.NET,Java等编程语言中的触发器。

Spring AOP模块提供拦截器来拦截应用程序。 例如,执行方法时,可以在方法执行之前或之后添加额外的功能。

AOP术语

在我们开始使用AOP之前,让我们熟悉AOP概念和术语。 这些术语并非特定于Spring,而是与AOP相关。

Sr.No 条款和说明
1

Aspect

这是一个模块,它有一组提供交叉要求的API。 例如,日志记录模块将被称为AOP方面以进行日志记录。 根据要求,应用程序可以具有任意数量的方面。

2

Join point

这代表了您可以插入AOP方面的应用程序中的一个点。 您还可以说,它是应用程序中使用Spring AOP框架执行操作的实际位置。

3

Advice

这是在方法执行之前或之后要采取的实际操作。 这是Spring AOP框架在程序执行期间调用的实际代码段。

4

Pointcut

这是一组应该执行建议的一个或多个连接点。 您可以使用表达式或模式指定切入点,我们将在AOP示例中看到。

5

Introduction

介绍允许您向现有类添加新方法或属性。

6

Target object

由一个或多个方面建议的对象。 此对象始终是代理对象,也称为建议对象。

7

Weaving

编织是将方面与其他应用程序类型或对象链接以创建建议对象的过程。 这可以在编译时,加载时或运行时完成。

建议类型

Spring方面可以使用如下提到的五种建议 -

Sr.No 建议和说明
1

before

在方法执行之前运行建议。

2

after

无论结果如何,在方法执行后运行建议。

3

after-returning

仅在方法成功完成时,在方法执行后运行建议。

4

after-throwing

仅在方法通过抛出异常退出时才在方法执行后运行建议。

5

around

在调用建议方法之前和之后运行建议。

自定义方面的实施

Spring支持@AspectJ annotation style方法和schema-based方法来实现自定义方面。 以下各节详细介绍了这两种方法。

Sr.No 方法和描述
1 基于XML Schema

使用常规类以及基于XML的配置来实现方面。

2 @AspectJ基于

@AspectJ指的是将方面声明为使用Java 5注释注释的常规Java类的样式。

Spring - JDBC Framework Overview

使用普通旧JDBC处理数据库时,编写不必要的代码来处理异常,打开和关闭数据库连接等变得很麻烦。但是,Spring JDBC Framework从打开连接开始处理所有低级细节,准备并执行SQL语句,处理异常,处理事务并最终关闭连接。

因此,您需要做的只是定义连接参数并指定要执行的SQL语句,并在从数据库中获取数据时为每次迭代执行所需的工作。

Spring JDBC提供了几种方法和相应的不同类来与数据库进行交互。 我将采用经典和最流行的方法来利用框架的JdbcTemplate类。 这是管理所有数据库通信和异常处理的中央框架类。

JdbcTemplate类

JDBC Template类执行SQL查询,更新语句,存储过程调用,对ResultSet执行迭代,并提取返回的参数值。 它还捕获JDBC异常并将它们转换为org.springframework.dao包中定义的通用的,更具信息性的异常层次结构。

一旦配置, JdbcTemplate类的实例就是threadsafe 。 因此,您可以配置JdbcTemplate的单个实例,然后将此共享引用安全地注入多个DAO。

使用JDBC Template类时的一种常见做法是在Spring配置文件中配置DataSource ,然后将共享DataSource bean依赖注入到DAO类中,并在DataSource的setter中创建JdbcTemplate。

配置数据源

让我们在数据库TEST创建一个数据库表Student 。 我们假设您正在使用MySQL数据库,如果您使用任何其他数据库,那么您可以相应地更改您的DDL和SQL查询。

CREATE TABLE Student(
   ID   INT NOT NULL AUTO_INCREMENT,
   NAME VARCHAR(20) NOT NULL,
   AGE  INT NOT NULL,
   PRIMARY KEY (ID)
);

现在我们需要向JDBC模板提供一个DataSource,以便它可以自行配置以获取数据库访问权限。 您可以使用一段代码在XML文件中配置DataSource,如以下代码段所示 -

<bean id = "dataSource" 
   class = "org.springframework.jdbc.datasource.DriverManagerDataSource">
   <property name = "driverClassName" value = "com.mysql.jdbc.Driver"/>
   <property name = "url" value = "jdbc:mysql://localhost:3306/TEST"/>
   <property name = "username" value = "root"/>
   <property name = "password" value = "password"/>
</bean>

Data Access Object (DAO)

DAO代表数据访问对象,它通常用于数据库交互。 存在DAO以提供向数据库读取和写入数据的方法,并且它们应该通过接口公开此功能,应用程序的其余部分将通过该接口访问它们。

Spring中的DAO支持使得以一致的方式使用JDBC,Hibernate,JPA或JDO等数据访问技术变得容易。

执行SQL语句

让我们看看如何使用SQL和JDBC Template对象对数据库表执行CRUD(创建,读取,更新和删除)操作。

Querying for an integer

String SQL = "select count(*) from Student";
int rowCount = jdbcTemplateObject.queryForInt( SQL );

Querying for a long

String SQL = "select count(*) from Student";
long rowCount = jdbcTemplateObject.queryForLong( SQL );

A simple query using a bind variable

String SQL = "select age from Student where id = ?";
int age = jdbcTemplateObject.queryForInt(SQL, new Object[]{10});

Querying for a String

String SQL = "select name from Student where id = ?";
String name = jdbcTemplateObject.queryForObject(SQL, new Object[]{10}, String.class);

Querying and returning an object

String SQL = "select * from Student where id = ?";
Student student = jdbcTemplateObject.queryForObject(
   SQL, new Object[]{10}, new StudentMapper());
public class StudentMapper implements RowMapper<Student> {
   public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
      Student student = new Student();
      student.setID(rs.getInt("id"));
      student.setName(rs.getString("name"));
      student.setAge(rs.getInt("age"));
      return student;
   }
}

Querying and returning multiple objects

String SQL = "select * from Student";
List<Student> students = jdbcTemplateObject.query(
   SQL, new StudentMapper());
public class StudentMapper implements RowMapper<Student> {
   public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
      Student student = new Student();
      student.setID(rs.getInt("id"));
      student.setName(rs.getString("name"));
      student.setAge(rs.getInt("age"));
      return student;
   }
}

Inserting a row into the table

String SQL = "insert into Student (name, age) values (?, ?)";
jdbcTemplateObject.update( SQL, new Object[]{"Zara", 11} );

Updating a row into the table

String SQL = "update Student set name = ? where id = ?";
jdbcTemplateObject.update( SQL, new Object[]{"Zara", 10} );

Deleting a row from the table

String SQL = "delete Student where id = ?";
jdbcTemplateObject.update( SQL, new Object[]{20} );

执行DDL语句

您可以使用jdbcTemplateexecute(..)方法来执行任何SQL语句或DDL语句。 以下是使用CREATE语句创建表的示例 -

String SQL = "CREATE TABLE Student( " +
   "ID   INT NOT NULL AUTO_INCREMENT, " +
   "NAME VARCHAR(20) NOT NULL, " +
   "AGE  INT NOT NULL, " +
   "PRIMARY KEY (ID));"
jdbcTemplateObject.execute( SQL );

Spring JDBC Framework示例

基于以上概念,让我们检查几个重要的例子,它们将帮助您理解Spring中JDBC框架的用法 -

Sr.No. 示例和说明
1 Spring JDBC示例

这个例子将解释如何编写一个简单的基于JDBC的Spring应用程序。

2 Spring中的SQL存储过程

学习如何在Spring中使用JDBC时调用SQL存储过程。

Spring - Transaction Management

数据库事务是一系列被视为单个工作单元的操作。 这些操作应该完全完成或根本不起作用。 事务管理是面向RDBMS的企业应用程序的重要组成部分,可确保数据的完整性和一致性。 交易的概念可以用以下描述为ACID四个关键属性来描述 -

  • Atomicity - 事务应被视为单个操作单元,这意味着整个操作序列成功或不成功。

  • Consistency - 这表示数据库的参照完整性,表中的唯一主键等的一致性。

  • Isolation - 可能会有许多事务处理同时使用相同的数据集。 每个事务都应与其他事务隔离,以防止数据损坏。

  • Durability - 事务完成后,此事务的结果必须是永久性的,并且由于系统故障而无法从数据库中删除。

真正的RDBMS数据库系统将保证每个事务的所有四个属性。 使用SQL向数据库发出的事务的简单视图如下 -

  • 使用begin transaction命令begin transaction

  • 使用SQL查询执行各种删除,更新或插入操作。

  • 如果所有操作都成功,则执行commit否则rollback所有操作。

Spring框架在不同的底层事务管理API之上提供了一个抽象层。 Spring的事务支持旨在通过向POJO添加事务功能来提供EJB事务的替代方法。 Spring支持编程和声明式事务管理。 EJB需要应用程序服务器,但可以在不需要应用程序服务器的情况下实现Spring事务管理。

本地与全球交易

本地事务特定于单个事务资源(如JDBC连接),而全局事务可以跨越多个事务资源,如分布式系统中的事务。

本地事务管理在应用程序组件和资源位于单个站点的集中式计算环境中非常有用,而事务管理仅涉及在单个机器上运行的本地数据管理器。 本地交易更容易实施。

在分布式计算环境中需要全局事务管理,其中所有资源都分布在多个系统中。 在这种情况下,交易管理需要在本地和全球层面进行。 跨多个系统执行分布式或全局事务,并且其执行需要全局事务管理系统与所有涉及系统的所有本地数据管理器之间的协调。

程序化与声明性

Spring支持两种类型的事务管理 -

  • 程序化事务管理 - 这意味着您必须在编程的帮助下管理事务。 这为您提供了极大的灵活性,但很难维护。

  • 声明式事务管理 - 这意味着您将事务管理与业务代码分开。 您只能使用注释或基于XML的配置来管理事务。

声明式事务管理优于程序化事务管理,但它不如程序化事务管理灵活,后者允许您通过代码控制事务。 但作为一种横切关注点,声明式事务管理可以通过AOP方法进行模块化。 Spring通过Spring AOP框架支持声明式事务管理。

Spring事务抽象

Spring事务抽象的关键是由org.springframework.transaction.PlatformTransactionManager接口定义,如下所示 -

public interface PlatformTransactionManager {
   TransactionStatus getTransaction(TransactionDefinition definition);
   throws TransactionException;
   void commit(TransactionStatus status) throws TransactionException;
   void rollback(TransactionStatus status) throws TransactionException;
}

Sr.No 方法和描述
1

TransactionStatus getTransaction(TransactionDefinition definition)

此方法根据指定的传播行为返回当前活动的事务或创建新事务。

2

void commit(TransactionStatus status)

此方法就其状态提交给定事务。

3

void rollback(TransactionStatus status)

此方法执行给定事务的回滚。

TransactionDefinition是Spring中事务支持的核心接口,定义如下 -

public interface TransactionDefinition {
   int getPropagationBehavior();
   int getIsolationLevel();
   String getName();
   int getTimeout();
   boolean isReadOnly();
}

Sr.No 方法和描述
1

int getPropagationBehavior()

此方法返回传播行为。 Spring提供了EJB CMT熟悉的所有事务传播选项。

2

int getIsolationLevel()

此方法返回此事务与其他事务的工作隔离的程度。

3

String getName()

此方法返回此事务的名称。

4

int getTimeout()

此方法返回事务必须完成的时间(以秒为单位)。

5

boolean isReadOnly()

此方法返回事务是否为只读。

以下是隔离级别的可能值 -

Sr.No 隔离和描述
1

TransactionDefinition.ISOLATION_DEFAULT

这是默认的隔离级别。

2

TransactionDefinition.ISOLATION_READ_COMMITTED

表示禁止脏读; 可以发生不可重复的读取和幻像读取。

3

TransactionDefinition.ISOLATION_READ_UNCOMMITTED

表示可能发生脏读,不可重复读和幻像读。

4

TransactionDefinition.ISOLATION_REPEATABLE_READ

表示禁止脏读和不可重复读; 可以发生幻像读取。

5

TransactionDefinition.ISOLATION_SERIALIZABLE

表示禁止脏读,不可重复读和幻像读。

以下是传播类型的可能值 -

Sr.No. 传播与描述
1

TransactionDefinition.PROPAGATION_MANDATORY

支持当前交易; 如果不存在当前事务,则抛出异常。

2

TransactionDefinition.PROPAGATION_NESTED

如果存在当前事务,则在嵌套事务中执行。

3

TransactionDefinition.PROPAGATION_NEVER

不支持当前交易; 如果存在当前事务,则抛出异常。

4

TransactionDefinition.PROPAGATION_NOT_SUPPORTED

不支持当前交易; 而且总是非交易地执行。

5

TransactionDefinition.PROPAGATION_REQUIRED

支持当前交易; 如果不存在,则创建一个新的。

6

TransactionDefinition.PROPAGATION_REQUIRES_NEW

创建一个新事务,暂停当前事务(如果存在)。

7

TransactionDefinition.PROPAGATION_SUPPORTS

支持当前交易; 如果不存在则以非事务方式执行。

8

TransactionDefinition.TIMEOUT_DEFAULT

使用基础事务系统的默认超时,如果不支持超时,则使用no​​ne。

TransactionStatus接口为事务代码提供了一种控制事务执行和查询事务状态的简单方法。

public interface TransactionStatus extends SavepointManager {
   boolean isNewTransaction();
   boolean hasSavepoint();
   void setRollbackOnly();
   boolean isRollbackOnly();
   boolean isCompleted();
}

Sr.No. 方法和描述
1

boolean hasSavepoint()

此方法返回此事务是否内部携带保存点,即是否已基于保存点创建为嵌套事务。

2

boolean isCompleted()

此方法返回此事务是否已完成,即是否已提交或回滚。

3

boolean isNewTransaction()

如果当前事务是新事务,则此方法返回true。

4

boolean isRollbackOnly()

此方法返回事务是否已标记为仅回滚。

5

void setRollbackOnly()

此方法将事务设置为仅回滚。

Spring - MVC Framework

Spring Web MVC框架提供模型 - 视图 - 控制器(MVC)架构和现成的组件,可用于开发灵活且松散耦合的Web应用程序。 MVC模式导致应用程序的不同方面(输入逻辑,业务逻辑和UI逻辑)分离,同时在这些元素之间提供松散耦合。

  • Model封装了应用程序数据,通常它们将由POJO组成。

  • View负责呈现模型数据,通常它会生成客户端浏览器可以解释的HTML输出。

  • Controller负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。

DispatcherServlet

Spring Web模型 - 视图 - 控制器(MVC)框架是围绕处理所有HTTP请求和响应的DispatcherServlet设计的。 Spring Web MVC DispatcherServlet的请求处理工作流程如下图所示 -

Spring DispatcherServlet

以下是与DispatcherServlet的传入HTTP请求相对应的事件序列 -

  • 收到HTTP请求后, DispatcherServlet查询HandlerMapping以调用相应的Controller

  • Controller接受请求并根据使用的GET或POST方法调用适当的服务方法。 服务方法将基于定义的业务逻辑设置模型数据,并将视图名称返回给DispatcherServlet

  • DispatcherServlet将从ViewResolver获取帮助以获取请求的已定义视图。

  • 一旦视图完成, DispatcherServlet将模型数据传递给最终在浏览器上呈现的视图。

所有上述组件,即HandlerMapping,Controller和ViewResolver都是WebApplicationContext w的一部分,它是普通ApplicationContext的扩展,具有Web应用程序所需的一些额外功能。

必需的配置

您需要使用web.xml文件中的URL映射来映射您希望DispatcherServlet处理的请求。 以下是显示HelloWeb DispatcherServlet示例的声明和映射的示例 -

<web-app id = "WebApp_ID" version = "2.4"
   xmlns = "http://java.sun.com/xml/ns/j2ee" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/j2ee 
   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
   <display-name>Spring MVC Application</display-name>
   <servlet>
      <servlet-name>HelloWeb</servlet-name>
      <servlet-class>
         org.springframework.web.servlet.DispatcherServlet
      </servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>
   <servlet-mapping>
      <servlet-name>HelloWeb</servlet-name>
      <url-pattern>*.jsp</url-pattern>
   </servlet-mapping>
</web-app>

web.xml文件将保存在Web应用程序的WebContent/WEB-INF目录中。 在初始化HelloWeb DispatcherServlet时,框架将尝试从位于应用程序的WebContent/WEB-INFdirectory中的名为[servlet-name]-servlet.xml的文件加载应用程序上下文。 在这种情况下,我们的文件将是HelloWebservlet.xml

接下来,标记指示哪个URL将由哪个DispatcherServlet处理。 这里以.jsp结尾的所有HTTP请求都将由HelloWeb DispatcherServlet处理。

如果您不希望使用默认文件名作为[servlet-name]-servlet.xml并将默认位置作为WebContent/WEB-INF ,则可以通过在web.xml文件中添加servlet侦听器ContextLoaderListener来自定义此文件名和位置如下 -

<web-app...>
   <!-------- <i>DispatcherServlet</i> definition goes here----->
   ....
   <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/HelloWeb-servlet.xml</param-value>
   </context-param>
   <listener>
      <listener-class>
         org.springframework.web.context.ContextLoaderListener
      </listener-class>
   </listener>
</web-app>

现在,让我们检查HelloWeb-servlet.xml文件所需的配置,该文件放在Web应用程序的WebContent/WEB-INF目录中 -

<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:context = "http://www.springframework.org/schema/context"
   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.0.xsd
   http://www.springframework.org/schema/context 
   http://www.springframework.org/schema/context/spring-context-3.0.xsd">
   <context:component-scan base-package = "com.iowiki" />
   <bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name = "prefix" value = "/WEB-INF/jsp/" />
      <property name = "suffix" value = ".jsp" />
   </bean>
</beans>

以下是关于HelloWeb-servlet.xml文件的重点 -

  • [servlet-name]-servlet.xml文件将用于创建定义的bean,覆盖在全局范围内使用相同名称定义的任何bean的定义。

  • 《context:component-scan...》标签将用于激活Spring MVC注释扫描功能,该功能允许使用@Controller和@RequestMapping等注释。

  • InternalResourceViewResolver将定义用于解析视图名称的规则。 根据上面定义的规则,名为hello的逻辑视图被委托给位于/WEB-INF/jsp/hello.jsp的视图实现。

以下部分将向您展示如何创建实际组件,即Controller,Model和View。

定义控制器

DispatcherServlet将请求委托给控制器以执行特定于它的功能。 @Controller注释指示特定类充当控制器的角色。 @RequestMapping注释用于将URL映射到整个类或特定的处理程序方法。

@Controller
@RequestMapping("/hello")
public class HelloController { 
   @RequestMapping(method = RequestMethod.GET)
   public String printHello(ModelMap model) {
      model.addAttribute("message", "Hello Spring MVC Framework!");
      return "hello";
   }
}

@Controller注释将类定义为Spring MVC控制器。 这里,@ @RequestMapping的第一次使用表明该控制器上的所有处理方法都与/hello路径相关。 下一个注释@RequestMapping(method = RequestMethod.GET)用于将printHello()方法声明为控制器处理HTTP GET请求的默认服务方法。 您可以定义另一种方法来处理同一URL上的任何POST请求。

您可以用另一种形式编写上述控制器,您可以在@RequestMapping添加其他属性,如下所示 -

@Controller
public class HelloController {
   @RequestMapping(value = "/hello", method = RequestMethod.GET)
   public String printHello(ModelMap model) {
      model.addAttribute("message", "Hello Spring MVC Framework!");
      return "hello";
   }
}

value属性指示处理程序方法映射到的URL, method属性定义处理HTTP GET请求的服务方法。 关于上面定义的控制器,需要注意以下要点 -

  • 您将在服务方法中定义所需的业务逻辑。 您可以根据需要在此方法中调用另一个方法。

  • 根据定义的业务逻辑,您将在此方法中创建模型。 您可以使用setter不同的模型属性,视图将访问这些属性以显示最终结果。 此示例创建一个具有其属性“message”的模型。

  • 定义的服务方法可以返回String,其中包含用于呈现模型的view的名称。 此示例返回“hello”作为逻辑视图名称。

创建JSP视图

Spring MVC支持不同类型的视图,用于不同的表示技术。 这些包括 - JSP,HTML,PDF,Excel工作表,XML,Velocity模板,XSLT,JSON,Atom和RSS提要,JasperReports等。但最常见的是我们使用用JSTL编写的JSP模板。

让我们在/WEB-INF/hello/hello.jsp中编写一个简单的hello视图 -

<html>
   <head>
      <title>Hello Spring MVC</title>
   </head>
   <body>
      <h2>${message}</h2>
   </body>
</html>

这里${message}是我们在Controller中设置的属性。 您可以在视图中显示多个属性。

Spring Web MVC框架示例

基于以上概念,让我们查看几个可以帮助您构建Spring Web应用程序的重要示例 -

Sr.No. 示例和说明
1 Spring MVC Hello World示例

这个例子将解释如何编写一个简单的Spring Web Hello World应用程序。

2 Spring MVC表单处理示例

此示例将说明如何使用HTML表单编写Spring Web应用程序以将数据提交到控制器并显示处理结果。

3 Spring页面重定向示例

学习如何在Spring MVC Framework中使用页面重定向功能。

4 Spring静态页面示例

了解如何在Spring MVC Framework中访问静态页面以及动态页面。

5 Spring异常处理示例

学习如何处理Spring MVC Framework中的异常。

Spring - Logging with Log4J

这是Spring应用程序中非常易于使用的Log4J功能。 下面的示例将指导您完成Log4J和Spring之间简单集成的简单步骤。

我们假设您的计算机上已经安装了log4J 。 如果你没有它,那么你可以从https://logging.apache.org/下载它,只需在任何文件夹中提取压缩文件。 我们将在项目中仅使用log4j-xyzjar

接下来,让我们使用一个可用的Eclipse IDE,并采用以下步骤使用Spring Web Framework开发基于动态表单的Web应用程序 -

脚步 描述
1 创建一个名为SpringExample的项目,并在创建的项目中的src文件夹下创建一个包com.iowiki
2 使用Add External JARs选项添加所需的Spring库,如Spring Hello World Example章节中所述。
3 使用Add External JARs在项目中添加log4j库log4j-xyzjar
4com.iowiki包下创建Java类HelloWorldMainApp
5src文件夹下创建Beans配置文件Beans.xml
6src文件夹下创建log4J配置文件log4j.properties
7 最后一步是创建所有Java文件和Bean配置文件的内容并运行应用程序,如下所述。

这是HelloWorld.java文件的内容

package com.iowiki;
public class HelloWorld {
   private String message;
   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage() {
      System.out.println("Your Message : " + message);
   }
}

以下是第二个文件MainApp.java的内容

package com.iowiki;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.apache.log4j.Logger;
public class MainApp {
   static Logger log = Logger.getLogger(MainApp.class.getName());
   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
      log.info("Going to create HelloWord Obj");
      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
      log.info("Exiting the program");
   }
}

您可以采用与生成信息消息类似的方式生成debugerror消息。 现在让我们看看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.0.xsd">
   <bean id = "helloWorld" class = "com.iowiki.HelloWorld">
      <property name = "message" value = "Hello World!"/>
   </bean>
</beans>

以下是log4j.properties的内容,它定义了Log4J生成日志消息所需的标准规则

# Define the root logger with appender file
log4j.rootLogger = DEBUG, FILE
# Define the file appender
log4j.appender.FILE=org.apache.log4j.FileAppender
# Set the name of the file
log4j.appender.FILE.File=C:\\log.out
# Set the immediate flush to true (default)
log4j.appender.FILE.ImmediateFlush=true
# Set the threshold to debug mode
log4j.appender.FILE.Threshold=debug
# Set the append to false, overwrite
log4j.appender.FILE.Append=false
# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%m%n

完成创建源和bean配置文件后,让我们运行应用程序。 如果您的应用程序一切正常,这将在Eclipse控制台中打印以下消息 -

Your Message : Hello World!

如果您检查C:\\驱动器,那么您应该找到包含各种日志消息的日志文件log.out ,如下所示 -

<!-- initialization log messages -->
Going to create HelloWord Obj
Returning cached instance of singleton bean 'helloWorld'
Exiting the program

Jakarta Commons Logging(JCL)API

或者,您可以使用Jakarta Commons Logging (JCL) API在Spring应用程序中生成日志。 可以从https://jakarta.apache.org/commons/logging/下载JCL。 我们技术上需要的唯一文件是commons-logging-xyzjar文件,它需要以与上面示例中的log4j-xyzjar类似的方式放置在类路径中。

要使用日志记录功能,您需要一个org.apache.commons.logging.Log对象,然后您可以根据您的要求调用以下方法之一 -

  • fatal(Object message)
  • 错误(对象消息)
  • warn(Object message)
  • info(Object message)
  • debug(Object message)
  • trace(Object message)

以下是MainApp.java的替换,它使用了JCL API

package com.iowiki;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.apache.commons.logging. Log;
import org.apache.commons.logging. LogFactory;
public class MainApp {
   static Log log = LogFactory.getLog(MainApp.class.getName());
   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
      log.info("Going to create HelloWord Obj");
      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
      log.info("Exiting the program");
   }
}

在编译和运行程序之前,您必须确保在项目中包含了commons-logging-xyzjar文件。

现在,在上面的示例中保持其余配置和内容不变,如果编译并运行应用程序,您将获得与使用Log4J API相似的结果。

↑回到顶部↑
WIKI教程 @2018