乐趣区

关于java:五Spring从入门到入土Bean的作用域与生命周期

Bean 的作用域

​ 在 Spring 中,那些组成应用程序的主体及由 Spring IoC 容器所治理的对象,被称之为 bean。简略地讲,bean 就是由 IoC 容器初始化、拆卸及治理的对象

类别 阐明
singleton(单例模式) 在 Spring Ioc 容器中仅存在一个 Bean 实例,Bean 以单例形式存在,默认模式下即为单例
prototype(原型模式) 每次从容器中调用 Bean 时,都返回一个新的实例,即每次调用 getBean()时,相等于执行 new.XxxBean()
request(HTTP 申请) 每次 HTTP 申请都会创立一个新的 Bean,该作用域仅实用于 WebApplicationContext 环境
session(会话) 同一个 HTTP Session 共享一个 Bean,不同 Session 应用不同 Bean,仅实用于 WebApplicationContext 环境
globalSession(全局会话) 个别用于 Portlet 应用环境,该作用域仅实用于 WebApplicationContext 环境

几种作用域中,request、session 作用域仅在基于 web 的利用中应用(不用关怀你所采纳的是什么 web 利用框架),只能用在基于 web 的 Spring ApplicationContext 环境。

Singleton(单例)

​ 当一个 bean 的作用域为 Singleton,那么 Spring IoC 容器中只会存在一个共享的 bean 实例,并且所有对 bean 的申请,只有 id 与该 bean 定义相匹配,则只会返回 bean 的同一实例。Singleton 是单例类型,就是在创立起容器时就同时主动创立了一个 bean 的对象,不论你是否应用,他都存在了,每次获取到的对象都是同一个对象。留神,Singleton 作用域是 Spring 中的缺省作用域。要在 XML 中将 bean 定义成 singleton,能够这样配置:

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

测试:

 @Test
 public void test03(){ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml");
     User user = (User) context.getBean("user");
     User user2 = (User) context.getBean("user");
     System.out.println(user==user2);
 }

Prototype

​ 当一个 bean 的作用域为 Prototype,示意一个 bean 定义对应多个对象实例。Prototype 作用域的 bean 会导致在每次对该 bean 申请(将其注入到另一个 bean 中,或者以程序的形式调用容器的 getBean() 办法)时都会创立一个新的 bean 实例。Prototype 是原型类型,它在咱们创立容器的时候并没有实例化,而是当咱们获取 bean 的时候才会去创立一个对象,而且咱们每次获取到的对象都不是同一个对象。依据教训,对有状态的 bean 应该应用 prototype 作用域,而对无状态的 bean 则应该应用 singleton 作用域。在 XML 中将 bean 定义成 prototype,能够这样配置:

 <bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>  
  或者
 <bean id="account" class="com.foo.DefaultAccount" singleton="false"/>

Request

​ 当一个 bean 的作用域为 Request,示意在一次 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

​ 当一个 bean 的作用域为 Session,示意在一个 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

​ 当一个 bean 的作用域为 Global Session,示意在一个全局的 HTTP Session 中,一个 bean 定义对应一个实例。典型状况下,仅在应用 portlet context 的时候无效。该作用域仅在基于 web 的 Spring ApplicationContext 情景下无效。思考上面 bean 定义:

<bean id="user" class="com.foo.Preferences"scope="globalSession"/>

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

Bean 的生命周期

对于一般的 Java 对象而言,生命周期绝对简略,new 的时候创建对象,当没有任何援用的时候被垃圾回收机制回收。

而由 Spring Ioc 容器托管的对象,它们的生命周期齐全由容器齐全管制。如下所示

实例化 Bean

实例化 Bean 时要看是 BeanFactory 容器还是 ApplicationContext 容器。

  • BeanFactory 容器:当向容器申请一个未初始的 bean 时,或初始化 bean 的时候须要注入注入到另一个尚未初始化的依赖时美容器就会调用 creatBean 来进行初始化
  • ApplicationContext 容器,当容器启动完结后,便实例化所有的 bean。
    • 容器通过获取 BeanDefinition 对象中的信息进行实例化。并且这一步仅仅是简略的实例化,并未进行依赖注入
    • 实例化对象被包装在 BeanWrapper 对象中,BeanWrapper 提供了设置对象属性的接口,从而防止了应用反射机制设置属性

设置对象属性(依赖注入)

实例化的对象被封装在 BeanWrapper 对象中,并且此时对象依然是一个原生的状态,并没有进行依赖注入

随后 Spring 依据 BeanDefinition 中的信息进行依赖注入,并且通过 BeanWrapper 提供的设置属性的接口实现依赖注入

注入 Aware 接口

随后 Spring 会检测该对象是否实现了 xxxAware 接口,并且将相干的实例注入给 bean。

此时 bean 对象曾经被正确结构。

BeanNameAware

如果 bean 实现此接口,spring 将 bean 的 id 传给 setBeanName() 办法

BeanFactoryAware

如果 bean 实现此接口,Spring 将调用 setBeanFactory 办法,将 BeanFactory 实例传过来

ApplicationContextAware

如果实现此接口,它的 setApplicationContext() 办法将被调用,将利用上下文的援用传入到 bean 中;

BeanPostProcessor

该接口提供了两个函数用来对对象在被应用前做一些自定义的解决,此时 Bean 会被传递进来,能够对 bean 做任何解决。

  • 前置解决:在 Bean 实例创立
    • postProcessBeforeInitialzation(Object bean, String beanName)
      • 会先于先于 InitialzationBean 执行,所有的 Aware 接口的注入就是在此实现的
  • 后置解决:
    • postProcessAfterInitialzation(Object bean, String beanName)

InitializingBean 与 init-method

以后置解决实现后就会进入本阶段。

  • afterPropertiesSet()

这一阶段也能够在 bean 正式结构实现前减少咱们自定义的逻辑,在这一步没方法解决对象自身,只能减少一些额定的逻辑。

若要应用它,咱们须要让 bean 实现该接口,并把要减少的逻辑写在该函数中。而后 Spring 会在前置解决实现后检测以后 bean 是否实现了该接口,并执行 afterPropertiesSet 函数。

当然,Spring 为了升高对客户代码的侵入性,给 bean 的配置提供了 init-method 属性,该属性指定了在这一阶段须要执行的函数名。Spring 便会在初始化阶段执行咱们设置的函数。init-method 实质上依然应用了 InitializingBean 接口。

DisposableBean 和 destroy-method

和 init-method 一样,通过给 destroy-method 指定函数,就能够在 bean 销毁前执行指定的逻辑。

最初

  • 如果感觉看完有播种,心愿能给我点个赞,这将会是我更新的最大能源,感激各位的反对
  • 欢送各位关注我的公众号【java 冢狐】,专一于 java 和计算机基础知识,保障让你看完有所播种,不信你打我
  • 如果看完有不同的意见或者倡议,欢送多多评论一起交换。感激各位的反对以及厚爱。

欢送关注公众号“Java 冢狐”,获取最新消息

退出移动版