欢迎来到Spring IoC示例教程。Spring框架是建立在控制反转原则上的。依赖注入是在应用程序中实现IoC的技术。
Spring IoC
今天我们将深入了解Spring IoC容器。我们还将介绍Spring Bean。以下是快速导航到Spring IoC教程不同部分的目录。
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 Bean` 没有什么特别之处,Spring 框架中通过 Spring 容器初始化的任何对象都称为 Spring Bean。如果通过提供配置元数据信息配置为通过容器初始化,则任何普通的 Java POJO 类都可以是 Spring Bean。
Spring Bean 作用域
有五个范围定义了Spring Beans。
- singleton – 每个容器只会创建一个bean的实例。这是Spring beans的默认范围。在使用这个范围时,请确保bean没有共享的实例变量,否则可能会导致数据不一致的问题。
- prototype – 每次请求bean时都会创建一个新的实例。
- request – 这与prototype范围相同,但是它是用于Web应用程序的。每个HTTP请求都会创建一个bean的新实例。
- session – 容器将为每个HTTP会话创建一个新的bean。
- global-session – 用于为Portlet应用程序创建全局会话bean。
Spring Framework是可扩展的,我们也可以创建自己的范围。然而,大多数情况下,我们使用框架提供的范围就足够了。
Spring Bean配置
Spring框架提供了三种配置bean供应用程序使用的方式。
- 基于注解的配置 – 通过使用@Service或@Component注解。作用域细节可以通过@Scope注解提供。
- 基于 XML 的配置 – 通过创建 Spring 配置 XML 文件来配置 bean。如果您正在使用 Spring MVC 框架,则可以通过在 web.xml 文件中编写一些样板代码来自动加载基于 xml 的配置。
- 基于 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 示例项目,并进行实际操作以更好地理解。
Source:
https://www.digitalocean.com/community/tutorials/spring-ioc-bean-example-tutorial