Spring学习(四):Spring Bean
Spring Bean
一 Spring Bean定义
Bean定义
被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的(例如,以XML<bean/ >定义的形式)
在容器本身内,这些bean定义表示为BeanDefinition对象,这些对象包含(除其他信息外)以下配置元数据:
- 如何创建一个bean
- bean的生命周期的详细信息
- bean的依赖关系
上述所有的配置元数据转换成一组构成每个 bean 定义的下列属性。
属性 | 描述 |
---|---|
id | Bean的唯一标识名。它必须是合法的XMLID,在整个XML文档中唯一。 |
name | 用来为id创建一个或多个别名。它可以是任意的字母符合。多个别名之间用逗号, 分号 或者空格。 |
class | 这个属性是强制性的,并且指定用来创建 bean 的 对象的全路径(com.zhang.pojo.Student)。 |
scope | 这个属性指定由特定的 bean 定义创建的对象的作用域 |
constructor-arg | 它是用来注入依赖关系的 |
properties | 它是用来注入依赖关系的 |
autowiring mode | 它是用来注入依赖关系的 |
lazy-initialization mode | 延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。 |
initialization | 在 bean 的所有必需的属性被容器设置之后,调用回调方法。 |
destruction | 当包含该 bean 的容器被销毁时,使用回调方法。 |
Bean 与 Spring 容器的关系
下图表达了Bean 与 Spring 容器之间的关系:
二 Spring Bean 作用域
Bean 的作用域
当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项。例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 singleton。
Spring 框架支持以下五个作用域,分别为 singleton、prototype、request、session 和 global session,5种作用域说明如下所示
作用域 | 描述 |
---|---|
singleton | 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值 |
prototype | 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean() |
request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 |
session | 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境 |
global-session | 一般用于Portlet应用环境,该作用域仅适用于WebApplicationContext环境 |
-
singleton 作用域:
singleton 是默认的作用域,也就是说,当定义 Bean 时,如果没有指定作用域配置项,则 Bean 的作用域被默认为 singleton。
当一个bean的作用域为 Singleton,那么 Spring IoC 容器中只会存在一个共享的 bean 实例,并且所有对 bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回 bean 的同一实例。Singleton 是单例类型,就是在创建起容器时就同时自动创建了一个 bean 的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton 作用域是 Spring 中的缺省作用域。你可以在 bean 的配置文件中设置作用域的属性为 singleton,如下所示:
<!-- A bean definition with singleton scope --> <bean id="..." class="..." scope="singleton"> <!-- collaborators and configuration for this bean go here --> </bean>
例子:
下面是Singleton.java的内容:
package com.zhang.work; public class Singleton { private String message; public void getMessage() { System.out.println(message); } public void setMessage(String message) { this.message = message; } }
下面是 MainApp.java 文件的内容:
package com.zhang.work; import javax.naming.Context; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import org.springframework.core.io.ClassPathResource; public class MainApp { public static void main(String[] args) { ApplicationContext factory = new ClassPathXmlApplicationContext("Beans.xml"); Singleton objA = factory.getBean("beanFactory", Singleton.class); objA.setMessage("I'm object A"); System.out.printf("objA输出:"); objA.getMessage(); Singleton objB = factory.getBean("beanFactory", Singleton.class); System.out.printf("objB输出:"); objB.getMessage(); } }
下面是 singleton 作用域必需的配置文件 Beans.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="beanFactory" class="com.zhang.work.Singleton" scope="singleton"> </bean> </beans>
输出信息:
-
prototype 作用域
当一个 bean 的作用域为 Prototype,表示一个 bean 定义对应多个对象实例。Prototype 作用域的 bean 会导致在每次对该 bean 请求(将其注入到另一个 bean 中,或者以程序的方式调用容器的 getBean() 方法)时都会创建一个新的 bean 实例。Prototype 是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的 bean 应该使用 prototype 作用域,而对无状态的bean则应该使用 singleton 作用域。
为了定义 prototype 作用域,你可以在 bean 的配置文件中设置作用域的属性为 prototype,如下所示:
<!-- A bean definition with singleton scope --> <bean id="..." class="..." scope="prototype"> <!-- collaborators and configuration for this bean go here --> </bean>
例子:
下面是Prototype.java的内容:
package com.zhang.work; public class Prototype { private String message; public void getMessage() { System.out.println(message); } public void setMessage(String message) { this.message = message; } }
下面是 MainApp.java 文件的内容:
package com.zhang.work; import javax.naming.Context; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import org.springframework.core.io.ClassPathResource; public class MainApp { public static void main(String[] args) { ApplicationContext factory = new ClassPathXmlApplicationContext("Beans.xml"); Prototype objA = factory.getBean("beanFactory", Prototype.class); objA.setMessage("I'm object A"); System.out.printf("objA输出:"); objA.getMessage(); Prototype objB = factory.getBean("beanFactory", Prototype.class); System.out.printf("objB输出:"); objB.getMessage(); } }
下面是 prototype 作用域必需的配置文件 Beans.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="beanFactory" class="com.zhang.work.Prototype" scope="prototype"> </bean> </beans>
输出信息:
三 Spring Bean 生命周期
Bean 的生命周期
当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态。同样,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作。
为了定义安装和拆卸一个 bean,我们只要声明带有 init-method 和/或 destroy-method 参数的 。init-method 属性指定一个方法,在实例化 bean 时,立即调用该方法。同样,destroy-method 指定一个方法,只有从容器中移除 bean 之后,才能调用该方法。
Bean的生命周期可以表达为:Bean的定义——Bean的初始化——Bean的使用——Bean的销毁
-
初始化回调
在基于 XML 的配置元数据的情况下,你可以使用 init-method 属性来指定带有 void 无参数方法的名称。例如:
<bean id="exampleBean" class="examples.ExampleBean" init-method="init"/>
下面是类的定义:
public class ExampleBean { public void init() { // do some initialization work } }
-
销毁回调
在基于 XML 的配置元数据的情况下,你可以使用 destroy-method 属性来指定带有 void 无参数方法的名称。例如:
<bean id="exampleBean" class="examples.ExampleBean" init-method="destroy"/>
下面是类的定义:
public class ExampleBean { public void destroy() { // do some destruction work } }
例子
这里是 LiveCycle.java 的文件的内容:
package com.zhang.work;
public class LifeCycle {
private String message;
public void getMessage() {
System.out.println(message);
}
public void setMessage(String message) {
this.message = message;
}
public void init(){
System.out.println("Bean is going through init.");
}
public void destroy(){
System.out.println("Bean will destroy now.");
}
}
下面是 MainApp.java 文件的内容。在这里,你需要注册一个在 AbstractApplicationContext 类中声明的关闭 hook 的 registerShutdownHook() 方法。它将确保正常关闭,并且调用相关的 destroy 方法。
package com.zhang.work;
import javax.naming.Context;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
public class MainApp {
public static void main(String[] args) {
AbstractApplicationContext factory = new ClassPathXmlApplicationContext("Beans.xml");
LifeCycle liveCycle = factory.getBean("lifeCycle",LifeCycle.class);
liveCycle.getMessage();
factory.registerShutdownHook();
}
}
下面是 init 和 destroy 方法必需的配置文件 Beans.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="lifeCycle" class="com.zhang.work.LifeCycle"
init-method="init" destroy-method="destroy">
<property name="message" value="This LiveCycle!"></property>
</bean>
</beans>
输出信息:
默认的初始化和销毁方法
如果你有太多具有相同名称的初始化或者销毁方法的 Bean,那么你不需要在每一个 bean 上声明初始化方法和销毁方法。框架使用 元素中的 default-init-method 和 default-destroy-method 属性提供了灵活地配置这种情况,如下所示:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-init-method="init"
default-destroy-method="destroy">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
</beans>
上一篇: Spring框架Bean大致内容
下一篇: Spring bean作用域介绍
推荐阅读
-
spring声明式事务学习笔记
-
一篇教你看懂spring bean工厂和aop
-
Spring MVC深入学习
-
我的开发经验分享(一)-Spring业务bean零配置
-
Spring的并发问题——有状态Bean和无状态Bean
-
Spring Bean 作用域
-
spring5源码解析—Bean的获取流程
-
Spring Cloud 学习Consul服务注册与发现
-
Redis缓存技术学习系列之事务处理 springmvc+mybatisdubbo+zookeeperrestful redis分布式缓存spring mvc
-
Redis缓存技术学习系列之事务处理 springmvc+mybatisdubbo+zookeeperrestful redis分布式缓存spring mvc