您的位置:首页 > 编程语言 > Java开发

Spring 4.0 学习日记(4)--- bean的作用域

2017-07-24 06:41 225 查看

Bean简介:

在spring中,那些组成你应用程序的主体(backbone)及由Spring IoC容器所管理的对象,被称之为bean。 简单地讲,bean就是由Spring容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别了。 而bean定义以及bean相互间的依赖关系将通过配置元数据来描述。

容纳bean

(1)bean工厂:最简单的容器,提供了基础的依赖注入支持,创建各种类型的bean

(2)应用上下文(ApplicationContext):建立在bean工厂基础之上,提供系统架构服务从ApplicationContext上下文容器中获取bean和从bean工厂容器中获取bean的区别

Bean的作用域

创建一个bean定义,其实质是用该bean定义对应的类来创建真正实例的“配方(recipe)”。把bean定义看成一个配方很有意义,它与class很类似,只根据一张“处方”就可以创建多个实例。

你不仅可以控制注入到对象中的各种依赖和配置值,还可以控制该对象的作用域。这样你可以灵活选择所建对象的作用域,而不必在Java Class级定义作用域。Spring Framework支持五种作用域(其中有三种只能用在基于web的Spring ApplicationContext)。

bean的作用域分类

Spring Framework支持五种作用域(其中有三种只能用在基于web的)。

singleton

在每个Spring IoC容器中一个bean定义对应一个对象实例。

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

注意:Singleton作用域是Spring中的缺省作用域。要在XML中将bean定义成singleton,可以这样配置:

<bean id="empServiceImpl" class="cn.csdn.service.EmpServiceImpl" scope="singleton">


prototype

一个bean定义对应多个对象实例。

一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

request

在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例,它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。

在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例, 它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。

考虑下面bean定义:

<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>


针对每次HTTP请求,Spring容器会根据loginAction bean定义创建一个全新的LoginAction bean实例, 且该loginAction bean实例仅在当前HTTP request内有效,因此可以根据需要放心的更改所建实例的内部状态, 而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。 当处理请求结束,request作用域的bean实例将被销毁。

session

在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

考虑下面bean定义:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>


针对某个HTTP Session,Spring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例, 且该userPreferences bean仅在当前HTTP Session内有效。 与request作用域一样,你可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例, 将不会看到这些特定于某个HTTP Session的状态变化。 当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉。

global session

在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。

在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。

考虑下面bean定义:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>


global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。

ps

假如你在编写一个标准的基于Servlet的web应用,并且定义了一个或多个具有global session作用域的bean,系统会使用标准的HTTP Session作用域,并且不会引起任何错误。

BeanFactory方式(已废弃)

BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
UserService userService = (UserService)factory.getBean("userService");
userService.sayHello();


此种方式实例化该容器时,bean不会被创建(lazy,速度慢,省内存),只有当你去使用bean时才进行加载。

移动设备使用BeanFactory(省内存)。其他九成用ApplicationContext

使用ApplicationContext时,并且为singleton时(prototype不可!),配置的bean不管你用不用,都被实例化(early,好处就是预加载,缺点就是耗内存)

或许bean的方法:

1     ClassPathXmlApplicationContext:从类路径中加载
2     FileSystemXmlApplicationContext: 从文件系统加载
3     XmlWebApplicationContext:从web系统中加载


bean的生命周期(scope=singleton为例说明)

(1)实例化(当程序加载beans.xml文件时),把我们的bean实例化到内存中,也可用factory-method 来调用有参的构造器

(2)设置属性,前提是有setter才能成功

(3)bean实现BeanNameAware接口,则可以通过setBeanName获取id号

(4)bean实现BeanFactoryAware接口,则可以获取beanFactory

(5)bean实现ApplicationContextAware接口,则调用setApplicationContext

(6)bean如果和一个后置处理器关联,则会调用两个方法,见下面的程序示例,执行”before“

(7)实现InitializingBean接口,则会调用afterPropertiesSet()方法

(8)调用定制(只有所配置的bean有,非aop)的初始化方法,xml bean里面写init-method

(9)后置处理器的”after“

(10)使用bean

(11)容器关闭

(12)bean实现DisposableBean的destroy()方法关闭数据连接,socket,文件流等

(13)调用定制的销毁方法 xml bean里面写 destroy-method

实际开发中用(1)(2)(6)(9)(10)(11)

BeanFactory 的话少了(5)(6)(9)

MyBeanPostProcessor.java
package com.myBeanPostProcessor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/** * Created by balfish on 15-3-29. */

class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
System.out.println("postProcessBeforeInitialization 函数被调用");
   return o;
}

@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
System.out.println("postProcessAfterInitialization 函数被调用");
   return o;
  }
}


applicationContext.xml的变化

<bean id="myBeanPostProcessor" class="com.myBeanPostProcessor.MyBeanPostProcessor" />


应用场景举例

1 记录每个对象实例化的时间

2过滤每个调用ip

3给所有对象添加属性,或者函数(面向切面aop)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring