Spring IoC,Spring Bean示例教程

时间:2020-02-23 14:35:52  来源:igfitidea点击:

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

SpringIoC

今天,我们将研究Spring IoC容器。
我们还将介绍Spring Bean。
下表是内容列表,可快速导航到Spring IoC教程的不同部分。

  • SpringIoC
  • Spring Bean
  • Spring Bean 范围
  • Spring Bean配置
  • 基于Spring IoC和Spring Bean ExampleXML的Spring Bean配置
  • 基于注释的Spring Bean配置
  • 基于Java的Spring Bean配置

SpringIoC容器

Spring IoC是一种实现对象依赖关系之间松散耦合的机制。
为了在运行时实现对象的松散耦合和动态绑定,其他的汇编器对象会注入对象依赖项。
Spring IoC容器是将依赖项注入到对象中并使其可供我们使用的程序。
我们已经研究了如何使用Spring Dependency Injection在我们的应用程序中实现IoC。

Spring IoC容器类是org.springframework.beans和org.springframework.context包的一部分。
Spring IoC容器为我们提供了分离对象依赖关系的不同方法。

BeanFactory是Spring IoC容器的根接口。
ApplicationContext是BeanFactory接口的子接口,提供Spring AOP功能,i18n等。

" ApplicationContext"的一些有用的子接口是" ConfigurableApplicationContext"和" WebApplicationContext"。
Spring框架提供了许多有用的ApplicationContext实现类,我们可以使用它们来获取Spring上下文,然后获取Spring Bean。

我们使用的一些有用的ApplicationContext实现是:

  • AnnotationConfigApplicationContext:如果我们在独立的Java应用程序中使用Spring并为Configuration使用注释,那么我们可以使用它来初始化容器并获取Bean对象。

  • ClassPathXmlApplicationContext:如果我们在独立应用程序中具有spring bean配置xml文件,则可以使用此类加载文件并获取容器对象。

  • FileSystemXmlApplicationContext:与ClassPathXmlApplicationContext相似,除了可以从文件系统中的任何位置加载xml配置文件。

  • Web应用程序的AnnotationConfigWebApplicationContext和XmlWebApplicationContext。

通常,如果您正在使用Spring MVC应用程序,并且您的应用程序配置为使用Spring Framework,则在启动应用程序和请求Bean时会初始化Spring IoC容器,并自动注入依赖项。

但是,对于独立应用程序,您需要在应用程序中的某个位置初始化容器,然后使用它来获取spring bean。

Spring Bean

Spring Bean没什么特别的,我们通过Spring容器初始化的Spring框架中的任何对象都称为Spring Bean。
如果通过提供配置元数据信息将其配置为通过容器初始化,那么任何普通的Java POJO类都可以是Spring Bean。

Spring Bean 范围

Spring Bean定义了五个作用域。

  • 单例–将为每个容器创建一个bean实例。
    这是spring bean的默认范围。
    使用此范围时,请确保Bean没有共享的实例变量,否则可能会导致数据不一致问题。

  • prototype –每次请求bean时都会创建一个新实例。

  • 要求–与原型范围相同,但应用于网络应用程序。
    将为每个HTTP请求创建一个新的bean实例。

  • session –容器将为每个HTTP会话创建一个新bean。

  • global-session –用于为Portlet应用程序创建全局会话Bean。

Spring Framework是可扩展的,我们也可以创建自己的范围。
但是,大多数时候我们对框架提供的范围感到满意。

Spring Bean配置

Spring Framework提供了三种方法来配置要在应用程序中使用的bean。

  • 基于注释的配置–通过使用@Service或者@Component注释。
    范围详细信息可以通过@Scope注释提供。

  • 基于XML的配置–通过创建Spring Configuration XML文件来配置Bean。
    如果您使用的是Spring MVC框架,则可以通过在web.xml文件中编写一些样板代码来自动加载基于xml的配置。

  • 基于Java的配置–从Spring 3.0开始,我们可以使用Java程序配置Spring Bean。
    用于基于Java的配置的一些重要注释是@ Configuration,@ ComponentScan和@Bean。

Spring IoC和Spring Bean示例项目

让我们通过一个简单的Spring项目来查看Spring IoC容器和Spring Bean配置的不同方面。

对于我的示例,我正在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.theitroad.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.theitroad.spring" 
	
	<beans:bean name="myBean" class="com.theitroad.spring.beans.MyBean" scope="singleton" ></beans:bean>
	
</beans:beans>

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

基于注释的Spring Bean配置

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

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

Spring IoC控制器类

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

package com.theitroad.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.theitroad.spring.beans.MyAnnotatedBean;
import com.theitroad.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 Framework配置应用程序,以便配置元数据将被加载并且上下文将被初始化。

<?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.theitroad.spring.main;

import java.util.Date;

public class MyService {

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

MyService是带有某些方法的简单Java类。

package com.theitroad.spring.main;

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

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

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

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

package com.theitroad.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);