Spring Bean

Posted 夜微凉、的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Bean相关的知识,希望对你有一定的参考价值。

  1. Spring Bean 定义

  2. Spring Bean 作用域

  3. Spring Bean 生命周期

  4. Spring Bean 后置处理器

  5. Spring Bean 定义继承

Spring Bean 定义

被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的,例如,已经在先前章节看到的,在 XML 的表单中的 定义。

bean 定义包含称为配置元数据的信息,下述容器也需要知道配置元数据:

  • 如何创建一个 bean

  • bean 的生命周期的详细信息

  • bean 的依赖关系

上述所有的配置元数据转换成一组构成每个 bean 定义的下列属性。

属性描述
class 这个属性是强制性的,并且指定用来创建 bean 的 bean 类。
name 这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID 和/或 name 属性来指定 bean 标识符。
scope 这个属性指定由特定的 bean 定义创建的对象的作用域,它将会在 bean 作用域的章节中进行讨论。
constructor-arg 它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
properties 它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
autowiring mode 它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
lazy-initialization mode 延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。
initialization 方法 在 bean 的所有必需的属性被容器设置之后,调用回调方法。它将会在 bean 的生命周期章节中进行讨论。
destruction 方法 当包含该 bean 的容器被销毁时,使用回调方法。它将会在 bean 的生命周期章节中进行讨论。

Bean 与 Spring 容器的关系

下图表达了Bean 与 Spring 容器之间的关系:

技术图片

Spring 配置元数据

Spring IoC 容器完全由实际编写的配置元数据的格式解耦。有下面三个重要的方法把配置元数据提供给 Spring 容器:

  • 基于 XML 的配置文件

  • 基于注解的配置

  • 基于 Java 的配置

提示:对于基于 XML 的配置,Spring 2.0 以后使用 Schema 的格式,使得不同类型的配置拥有了自己的命名空间,是配置文件更具扩展性。

你已经看到了如何把基于 XML 的配置元数据提供给容器,但是让我们看看另一个基于 XML 配置文件的例子,这个配置文件中有不同的 bean 定义,包括延迟初始化,初始化方法和销毁方法的:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 
 3 <beans xmlns="http://www.springframework.org/schema/beans"
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5     xsi:schemaLocation="http://www.springframework.org/schema/beans
 6     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 7 
 8    <!-- A simple bean definition -->
 9    <bean id="..." class="...">
10        <!-- collaborators and configuration for this bean go here -->
11    </bean>
12 
13    <!-- A bean definition with lazy init set on -->
14    <bean id="..." class="..." lazy-init="true">
15        <!-- collaborators and configuration for this bean go here -->
16    </bean>
17 
18    <!-- A bean definition with initialization method -->
19    <bean id="..." class="..." init-method="...">
20        <!-- collaborators and configuration for this bean go here -->
21    </bean>
22 
23    <!-- A bean definition with destruction method -->
24    <bean id="..." class="..." destroy-method="...">
25        <!-- collaborators and configuration for this bean go here -->
26    </bean>
27 
28    <!-- more bean definitions go here -->
29 
30 </beans>

在上述示例中:

①xmlns="http://www.springframework.org/schema/beans",默认命名空间:它没有空间名,用于Spring Bean的定义;

②xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance",xsi命名空间:这个命名空间用于为每个文档中命名空间指定相应的Schema样式文件,是标准组织定义的标准命名空间。

Spring Bean 作用域

Bean 的作用域

当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项。例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 singleton

Spring 框架支持以下五个作用域,分别为singleton、prototype、request、session和global session,5种作用域说明如下所示,

注意,如果你使用 web-aware ApplicationContext 时,其中三个是可用的。    

作用域描述
singleton

在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值

prototype 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()
request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境
global-session 一般用于Portlet应用环境,该运用域仅适用于WebApplicationContext环境

本章将讨论前两个范围,当我们将讨论有关 web-aware Spring ApplicationContext 时,其余三个将被讨论。

singleton 作用域:

singleton 是默认的作用域,也就是说,当定义 Bean 时,如果没有指定作用域配置项,则 Bean 的作用域被默认为 singleton。

当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。

也就是说,当将一个bean定义设置为singleton作用域的时候,Spring IoC容器只会创建该bean定义的唯一实例。

Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。

注意,Singleton作用域是Spring中的缺省作用域。你可以在 bean 的配置文件中设置作用域的属性为 singleton,如下所示:

1 <!-- A bean definition with singleton scope -->
2 <bean id="..." class="..." scope="singleton">
3     <!-- collaborators and configuration for this bean go here -->
4 </bean>

例子

这里是 HelloWorld.java 文件的内容:

 1 package com.tutorialspoint;
 2 public class HelloWorld {
 3    private String message;
 4    public void setMessage(String message){
 5       this.message  = message;
 6    }
 7    public void getMessage(){
 8       System.out.println("Your Message : " + message);
 9    }
10 }

下面是 MainApp.java 文件的内容:

 1 package com.tutorialspoint;
 2 import org.springframework.context.ApplicationContext;
 3 import org.springframework.context.support.ClassPathXmlApplicationContext;
 4 public class MainApp {
 5    public static void main(String[] args) {
 6       ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
 7       HelloWorld objA = (HelloWorld) context.getBean("helloWorld");
 8       objA.setMessage("I‘m object A");
 9       objA.getMessage();
10       HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
11       objB.getMessage();
12    }
13 }

下面是 singleton 作用域必需的配置文件 Beans.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 
 3 <beans xmlns="http://www.springframework.org/schema/beans"
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5     xsi:schemaLocation="http://www.springframework.org/schema/beans
 6     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 7 
 8    <bean id="helloWorld" class="com.tutorialspoint.HelloWorld" 
 9       scope="singleton">
10    </bean>
11 </beans>

一旦你创建源代码和 bean 配置文件完成后,我们就可以运行该应用程序。如果你的应用程序一切都正常,将输出以下信息:

Your Message : I‘m object A
Your Message : I‘m object A

prototype 作用域

当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)

时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。

根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

为了定义 prototype 作用域,你可以在 bean 的配置文件中设置作用域的属性为 prototype,如下所示:

1 <!-- A bean definition with singleton scope -->
2 <bean id="..." class="..." scope="prototype">
3    <!-- collaborators and configuration for this bean go here -->
4 </bean>

例子

这里是 HelloWorld.java 文件的内容:

 1 package com.tutorialspoint;
 2 
 3 public class HelloWorld {
 4    private String message;
 5 
 6    public void setMessage(String message){
 7       this.message  = message;
 8    }
 9 
10    public void getMessage(){
11       System.out.println("Your Message : " + message);
12    }
13 }

下面是 MainApp.java 文件的内容:

 1 package com.tutorialspoint;
 2 import org.springframework.context.ApplicationContext;
 3 import org.springframework.context.support.ClassPathXmlApplicationContext;
 4 public class MainApp {
 5    public static void main(String[] args) {
 6       ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
 7       HelloWorld objA = (HelloWorld) context.getBean("helloWorld");
 8       objA.setMessage("I‘m object A");
 9       objA.getMessage();
10       HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
11       objB.getMessage();
12    }
13 }

下面是 prototype 作用域必需的配置文件 Beans.xml:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 
 3 <beans xmlns="http://www.springframework.org/schema/beans"
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5     xsi:schemaLocation="http://www.springframework.org/schema/beans
 6     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 7 
 8    <bean id="helloWorld" class="com.tutorialspoint.HelloWorld" 
 9       scope="prototype">
10    </bean>
11 
12 </beans>

一旦你创建源代码和 Bean 配置文件完成后,我们就可以运行该应用程序。如果你的应用程序一切都正常,将输出以下信息:

Your Message : I‘m object A
Your Message : null

Spring Bean 生命周期

 

Spring Bean 后置处理器

 

Spring Bean 定义继承

 

以上是关于Spring Bean的主要内容,如果未能解决你的问题,请参考以下文章

[死磕 Spring 17/43] --- IOC 之从单例缓存中获取单例 bean

What's the difference between @Component, @Repository & @Service annotations in Spring?(代码片段

Bean后置处理器 - BeanPostProcessor#postProcessAfterInitialization

SpringBoot启动报错“Consider defining a bean of type ‘xxx.mapper.UserMapper‘ in your configuration.“(代码片段

spring bean的生命周期是怎样的,代码示例

报错“Field pet in XXX.HelloController required a bean of type ‘XXX.Pet‘ that could not be found.“(代码片段