Spring IoC,Spring Bean 示例教程

欢迎来到Spring IoC示例教程。Spring框架是建立在控制反转原则上的。依赖注入是在应用程序中实现IoC的技术。

Spring IoC

今天我们将深入了解Spring IoC容器。我们还将介绍Spring Bean。以下是快速导航到Spring IoC教程不同部分的目录。

  1. Spring IoC
  2. Spring Bean
  3. Spring Bean作用域
  4. Spring Bean配置
  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.beansorg.springframework.context包的一部分。Spring IoC容器提供了不同的方式来解耦对象的依赖关系。BeanFactory是Spring IoC容器的根接口。ApplicationContextBeanFactory接口的子接口,提供了Spring AOP功能,国际化等。一些有用的ApplicationContext的子接口包括ConfigurableApplicationContextWebApplicationContext。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 Bean` 没有什么特别之处,Spring 框架中通过 Spring 容器初始化的任何对象都称为 Spring Bean。如果通过提供配置元数据信息配置为通过容器初始化,则任何普通的 Java POJO 类都可以是 Spring Bean。

Spring Bean 作用域

有五个范围定义了Spring Beans。

  1. singleton – 每个容器只会创建一个bean的实例。这是Spring beans的默认范围。在使用这个范围时,请确保bean没有共享的实例变量,否则可能会导致数据不一致的问题。
  2. prototype – 每次请求bean时都会创建一个新的实例。
  3. request – 这与prototype范围相同,但是它是用于Web应用程序的。每个HTTP请求都会创建一个bean的新实例。
  4. session – 容器将为每个HTTP会话创建一个新的bean。
  5. global-session – 用于为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 bean。一些用于基于 Java 的配置的重要注解包括@Configuration@ComponentScan@Bean

Spring IoC 和 Spring Bean 示例项目

让我们看一下 Spring IoC 容器和 Spring Bean 配置的不同方面,通过一个简单的 Spring 项目。对于我的示例,我在 Spring Tool Suite 中创建了一个 Spring MVC 项目。如果你是 Spring Tool Suite 和 Spring MVC 的新手,请阅读使用 Spring Tool Suite 的 Spring MVC 教程。最终的项目结构如下图所示。 让我们逐个查看 Spring IoC 和 Spring Bean 项目的不同组件。

基于 XML 的 Spring Bean 配置

MyBean 是一个简单的 Java POJO 类。

package com.journaldev.spring.beans;

public class MyBean {

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

Spring 配置 XML 文件

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 Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<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.journaldev.spring" />
	
	<beans:bean name="myBean" class="com.journaldev.spring.beans.MyBean" scope="singleton" ></beans:bean>
	
</beans:beans>

注意,MyBean 是使用bean元素配置的,作用域为 singleton。

基于注解的 Spring Bean 配置

package com.journaldev.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;
	}
	
}

MyAnnotatedBean 使用 @Service 进行配置,并将范围设置为 Request。

Spring IoC 控制器类

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

package com.journaldev.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.journaldev.spring.beans.MyAnnotatedBean;
import com.journaldev.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;
	}
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@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.journaldev.spring.main;

import java.util.Date;

public class MyService {

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

MyService 是一个简单的 Java 类,具有一些方法。

package com.journaldev.spring.main;

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

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

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

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

package com.journaldev.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();
	}

}

A simple test program where we are initializing the AnnotationConfigApplicationContext context and then using getBean() method to get the instance of MyService. Notice that I am calling getBean method two times and printing the hashcode. Since there is no scope defined for MyService, it should be a singleton and hence hashcode should be the same for both the instances. When we run the above application, we get following console output confirming our understanding.

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 项目

参考:Spring.IO IOC 页面

Source:
https://www.digitalocean.com/community/tutorials/spring-ioc-bean-example-tutorial