深入理解Spring IoC与Bean:完整示例教程与实战指南

欢迎来到 Spring IoC 示例教程。Spring Framework 是基于控制反转原则构建的。依赖注入是在应用中实现控制反转的技术。

Spring IoC(控制反转)

今天我们将研究Spring IoC容器。我们还将学习Spring Bean。以下是快速导航到Spring IoC教程不同部分的目录。

  1. Spring IoC(控制反转)
  2. Spring Bean(Spring对象)
  3. Spring Bean作用域(Spring对象范围)
  4. Spring Bean配置(Spring对象配置)
  5. Spring IoC和Spring Bean示例
    1. 基于XML的Spring Bean配置
    2. 基于注解的Spring Bean配置
    3. 基于Java的Spring Bean配置

Spring IoC容器

Spring IoC是实现对象之间松散耦合的机制。为了在运行时实现松散耦合和动态绑定对象的依赖关系,对象的依赖关系由其他装配器对象注入。Spring IoC容器是将依赖注入到对象中并使其准备好供我们使用的程序。我们已经了解了如何使用Spring依赖注入来实现IoC。Spring IoC容器类位于org.springframework.beans和org.springframework.context包中。Spring IoC容器为我们提供了不同的方法来解耦对象的依赖关系。BeanFactory是Spring IoC容器的根接口。ApplicationContext是BeanFactory接口的子接口,提供了Spring AOP的功能,国际化等。ApplicationContext的一些有用的子接口包括ConfigurableApplicationContext和WebApplicationContext。Spring框架提供了许多有用的ApplicationContext实现类,我们可以使用它们来获取Spring上下文,然后获取Spring Bean。我们使用的一些有用的ApplicationContext实现包括:

  • AnnotationConfigApplicationContext: 如果我们在独立的Java应用程序中使用Spring并使用注解进行配置,那么我们可以使用它来初始化容器并获取bean对象。
  • ClassPathXmlApplicationContext: 如果我们在独立应用程序中有spring bean配置xml文件,那么我们可以使用这个类来加载文件并获取容器对象。
  • FileSystemXmlApplicationContext: 这与ClassPathXmlApplicationContext类似,不同之处在于xml配置文件可以从文件系统的任何位置加载。
  • AnnotationConfigWebApplicationContext和XmlWebApplicationContext用于Web应用程序。

通常情况下,如果您正在处理Spring MVC应用程序并且应用程序已配置为使用Spring框架,当应用程序启动时,Spring IoC容器会初始化,并且在请求Bean时会自动注入依赖项。然而,对于一个独立的应用程序,您需要在应用程序的某个位置初始化容器,然后使用它来获取Spring的Bean。

Spring Bean

在Spring框架中,Spring Bean并没有什么特别之处,它指的是通过Spring容器初始化的任何对象。只要通过提供配置元数据信息将普通的Java POJO类配置为通过容器初始化,它就可以成为Spring Bean。

Spring Bean 作用范围

Spring Beans有五个定义范围。

  1. 单例 – 每个容器只会创建一个实例。这是Spring Bean的默认范围。在使用此范围时,请确保bean没有共享实例变量,否则可能会导致数据不一致的问题。
  2. 原型 – 每次请求bean时都会创建一个新实例。
  3. 请求 – 这与原型范围类似,但是它适用于Web应用程序。每个HTTP请求都会创建一个新的bean实例。
  4. 会话 – 容器会为每个HTTP会话创建一个新的bean。
  5. 全局会话 – 用于创建Portlet应用程序的全局会话bean。

Spring Framework是可扩展的,我们也可以创建自己的范围。然而,大部分时间我们都满足于框架提供的范围。

Spring Bean配置

Spring框架提供了三种配置bean供应用程序使用的方法。

  1. 基于注解的配置 – 通过使用@Service或@Component注解。范围细节可以用@Scope注解提供。
  2. 基于XML的配置 – 通过创建Spring配置XML文件来配置bean。如果使用Spring MVC框架,可以通过在web.xml文件中编写一些样板代码来自动加载基于xml的配置。
  3. 基于Java的配置 – 从Spring 3.0开始,我们可以使用Java程序来配置Spring beans。一些重要的用于基于Java的配置的注解包括@Configuration,@ComponentScan和@Bean。

Spring IoC和Spring Bean示例项目

让我们来看一下在一个简单的Spring项目中,Spring IoC容器和Spring Bean配置的不同方面。作为我的例子,我将在Spring工具套件中创建一个Spring MVC项目。如果你是Spring工具套件和Spring MVC的新手,请阅读Spring MVC教程。最终的项目结构如下图所示。让我们逐个地看一下Spring IoC和Spring Bean项目的不同组件。

基于 XML 的 Spring Bean 配置

MyBean是一个简单的Java POJO类。

package com.Olivia.spring.beans;

public class MyBean {

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

Spring配置的XML文件

这是文章《Spring IoC,Spring Bean示例教程》的第2部分(共3部分)。

内容片段: servlet-context.xml的代码:

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

	<!-- DispatcherServlet上下文:定义此servlet的请求处理基础设施 -->
	
	<!-- 启用Spring MVC @Controller编程模型 -->
	<annotation-driven />

	<!-- 通过高效地提供${webappRoot}/resources目录中的静态资源来处理对/resources/**的HTTP GET请求 -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- 将由@Controllers选择用于渲染的视图解析为/WEB-INF/views目录中的.jsp资源 -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<context:component-scan base-package="com.Olivia.spring" />
	
	<beans:bean name="myBean" class="com.Olivia.spring.beans.MyBean" scope="singleton" ></beans:bean>
	
</beans:beans>

请注意,MyBean是使用作用域为单例的bean元素进行配置的。

基于注解的Spring Bean配置

package com.Olivia.spring.beans;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.web.context.WebApplicationContext;

@Service
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class MyAnnotatedBean {

	private int empId;

	public int getEmpId() {
		return empId;
	}

	public void setEmpId(int empId) {
		this.empId = empId;
	}
	
}

我的注解化Bean是通过@Service注解进行配置的,并且作用域被设置为Request。

Spring IoC控制器类

HomeController类将处理应用程序主页的HTTP请求。我们将通过WebApplicationContext容器将Spring beans注入到此控制器类中。

package com.Olivia.spring.controller;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.Olivia.spring.beans.MyAnnotatedBean;
import com.Olivia.spring.beans.MyBean;

@Controller
@Scope("request")
public class HomeController {
		
	private MyBean myBean;
	
	private MyAnnotatedBean myAnnotatedBean;

	@Autowired
	public void setMyBean(MyBean myBean) {
		this.myBean = myBean;
	}

	@Autowired
	public void setMyAnnotatedBean(MyAnnotatedBean obj) {
		this.myAnnotatedBean = obj;
	}
	
	/**
	 * 通过返回视图名称来简单选择要渲染的主页视图。
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		System.out.println("MyBean hashcode="+myBean.hashCode());
		System.out.println("MyAnnotatedBean hashcode="+myAnnotatedBean.hashCode());
		
		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
		
		String formattedDate = dateFormat.format(date);
		
		model.addAttribute("serverTime", formattedDate );
		
		return "home";
	}
	
}

部署描述符

我们需要为Spring框架配置应用程序,以便加载配置元数据并初始化上下文。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

几乎所有上述的配置都是由STS工具自动生成的模板代码。

运行Spring IoC Bean示例应用程序

现在,当您启动web应用程序时,主页将被加载,并且在控制台中,当您多次刷新页面时,以下日志将被打印出来。

MyBean hashcode=118267258
MyAnnotatedBean hashcode=1703899856
MyBean hashcode=118267258
MyAnnotatedBean hashcode=1115599742
MyBean hashcode=118267258
MyAnnotatedBean hashcode=516457106

请注意,MyBean被配置为单例,因此容器始终返回相同的实例,哈希码始终相同。同样,对于每个请求,都会创建一个具有不同哈希码的新实例MyAnnotatedBean。

基于Java的Spring Bean配置

对于独立应用程序,我们可以使用基于注解的配置和基于XML的配置。唯一的要求是在程序中的某个地方初始化上下文,之后才能使用它。

package com.Olivia.spring.main;

import java.util.Date;

public class MyService {

	public void log(String msg){
		System.out.println(new Date()+"::"+msg);
	}
}

我的服务是一个简单的Java类,拥有一些方法。

package com.Olivia.spring.main;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(value="com.Olivia.spring.main")
public class MyConfiguration {

	@Bean
	public MyService getService(){
		return new MyService();
	}
}

将用于初始化Spring容器的基于注解的配置类。

package com.Olivia.spring.main;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyMainClass {

	public static void main(String[] args) {
		
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
				MyConfiguration.class);
		MyService service = ctx.getBean(MyService.class);
		
		service.log("Hi");
		
		MyService newService = ctx.getBean(MyService.class);
		System.out.println("service hashcode="+service.hashCode());
		System.out.println("newService hashcode="+newService.hashCode());
		ctx.close();
	}

}

在这个简单的测试程序中,我们初始化了 AnnotationConfigApplicationContext 上下文,然后使用 getBean() 方法获得 MyService 的实例。请注意,我调用了 getBean 方法两次并打印了哈希码。由于 MyService 没有定义作用域,它应该是单例的,因此两个实例的哈希码应该是相同的。当我们运行上述应用程序时,我们会得到以下控制台输出,确认了我们的理解。

Sat Dec 28 22:49:18 PST 2013::Hi
service hashcode=678984726
newService hashcode=678984726

如果你正在寻找基于XML的配置方式,只需创建Spring XML配置文件,然后使用以下代码片段初始化上下文即可。

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        MyService app = context.getBean(MyService.class);

这就是关于Spring IoC示例教程、Spring Bean作用域和配置细节的全部内容。您可以从下面的链接中下载Spring IoC和Spring Bean示例项目,通过对其进行操作来更好地理解。

下载一个Spring Beans项目。

参考资料:IOC的Spring IO页面

bannerAds