Spring IoC、Spring Bean 示例教程
欢迎阅读 Spring IoC 示例教程。Spring 框架基于控制反转原理构建。依赖注入是在应用程序中实现 IoC 的技术。
春季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 特性、i18n 等。的一些有用的子接口ApplicationContext
是ConfigurableApplicationContext
和WebApplicationContext
。Spring 框架提供了许多有用的 ApplicationContext 实现类,我们可以使用这些类来获取 spring 上下文,然后获取 Spring Bean。我们使用的一些有用的 ApplicationContext 实现是;
- AnnotationConfigApplicationContext:如果我们在独立的 java 应用程序中使用 Spring 并使用配置注释,那么我们可以使用它来初始化容器并获取 Bean 对象。
- ClassPathXmlApplicationContext:如果我们在独立应用程序中有 spring bean 配置 xml 文件,那么我们可以使用此类来加载文件并获取容器对象。
- FileSystemXmlApplicationContext:这与 ClassPathXmlApplicationContext 类似,不同之处在于 xml 配置文件可以从文件系统中的任何位置加载。
- 用于 Web 应用程序的AnnotationConfigWebApplicationContext和XmlWebApplicationContext 。
通常,如果您正在使用 Spring MVC 应用程序,并且您的应用程序配置为使用 Spring Framework,则 Spring IoC 容器会在应用程序启动时初始化,并且当请求 bean 时,依赖项会自动注入。但是,对于独立应用程序,您需要在应用程序中的某个位置初始化容器,然后使用它来获取 spring bean。
Spring Bean
Spring Bean is nothing special, any object in the Spring framework that we initialize through Spring container is called Spring Bean. Any normal Java POJO class can be a Spring Bean if it’s configured to be initialized via container by providing configuration metadata information.
Spring Bean Scopes
There are five scopes defined for Spring Beans.
- singleton - Only one instance of the bean will be created for each container. This is the default scope for the spring beans. While using this scope, make sure bean doesn’t have shared instance variables otherwise it might lead to data inconsistency issues.
- prototype - A new instance will be created every time the bean is requested.
- request - This is same as prototype scope, however it’s meant to be used for web applications. A new instance of the bean will be created for each HTTP request.
- session - A new bean will be created for each HTTP session by the container.
- global-session - This is used to create global session beans for Portlet applications.
Spring Framework is extendable and we can create our own scopes too. However, most of the times we are good with the scopes provided by the framework.
Spring Bean Configuration
Spring Framework provides three ways to configure beans to be used in the application.
- Annotation Based Configuration - By using @Service or @Component annotations. Scope details can be provided with @Scope annotation.
- XML Based Configuration - By creating Spring Configuration XML file to configure the beans. If you are using Spring MVC framework, the xml based configuration can be loaded automatically by writing some boiler plate code in web.xml file.
- Java Based Configuration - Starting from Spring 3.0, we can configure Spring beans using java programs. Some important annotations used for java based configuration are @Configuration, @ComponentScan and @Bean.
Spring IoC and Spring Bean Example Project
Let’s look at the different aspects of Spring IoC container and Spring Bean configurations with a simple Spring project. For my example, I am creating a Spring MVC project in Spring Tool Suite. If you are new to Spring Tool Suite and Spring MVC, please read Spring MVC Tutorial with Spring Tool Suite. The final project structure looks like below image. Let’s look at different components of Spring IoC and Spring Bean project one by one.
XML Based Spring Bean Configuration
MyBean is a simple Java POJO class.
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 Configuration XML File
servlet-context.xml code:
<?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>
Notice that MyBean is configured using bean
element with scope as singleton.
Annotation Based Spring Bean Configuration
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 bean 注入到这个控制器类中。
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 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.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();
}
}
这是一个简单的测试程序,我们初始化上下文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 项目