Spring Bean

2016-03-23 18:39:07   最后更新: 2017-03-27 11:50:54   访问数量:703




依赖注入是控制反转的重要类型之一,控制反转即 IoC(Inversion of Control),是一种全新的设计模式,运用面向对象编程的法则解决程序的耦合问题,也是轻量级的 Spring 框架的核心

IoC 有两种类型:依赖注入和依赖查找,其中以依赖注入最为常用

 

scope 可以指定下列作用域之一:

spring bean 作用域选项
作用域意义
单例 singleton在每一个 Spring 容器中,一个 Bean 定义只有一个对象实例(默认)
原型 prototype每次调用都实例化一个新的实例
请求 request在一次 HTTP 请求中,每个 Bean 定义一个实例(仅用于 Spring MVC)
会话 session在一个 HTTP Session 中,每个 Bean 定义对应的一个实例(仅用于 Spring MVC)
全局会话 global-session在一个全局 HTTP Session 中,每个 Bean 定义对应一个实例(仅用于 Spring MVC)

 

默认的所有 Spring 的 Bean 都是单例的,也就是说,当容器分配一个 Bean 时,总是返回 Bean 的同一个实例

如果要改变默认行为,可以通过 scope 属性指定作用域:

<beans xmlns:aop="http://www.springframework.org/schema/aop"> <bean id="cart" class="com.techlog.test.dol.Cart" scope="session"/> <aop:scoped-proxy /> </beans>

 

 

也可以通过注解来实现:

@Component @Scope( value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.INTERFACES) public interface Cart { ... }

 

上面的配置实现了将购物车 Bean 设置为会话作用域,这样购物车将于每个登入的用户关联

 

需要注意的是,如果在一个 singleton 的 Controller 里调用一个 prototype 的 Service,那么 prototype 的 Service 将会被降级为一个单例的对象,因为 Controller 只会用到这个多例对象的一个实例

而 request、session、global-session 的 Service 都必须用在相同 Scope 的 Controller 里,不然在编译期程序就会报错了

 

上面的例子介绍了如何通过 scope 配置改变一个 Bean 的作用域

在配置中,同时还加入了 <aop:scoped-proxy /> 和 proxyMode=ScopedProxyMode.INTERFACES,这又是什么呢?

如果将 Cart Bean 注入到一个单例的 Bean 中,那么,在这个单例 Bean 会在 Spring 应用上下文加载的时候创建,当他创建时,Spring 会试图将 Cart Bean 注入到相应的方法或字段中,但 Cart Bean 是会话作用域的,此时并不存在,只有当用户进入系统创建会话以后才会创建 Cart 实例

同时,单例的 Bean 意味着整个 Spring 执行过程中,他都只有一个实例,而 Spring 将会为会话作用域的 Cart Bean 创建多个实例,每个用户一个,因此我们需要一个代理,Spring 将所有创建的 Cart Bean 实例都委托给这个代理,每当需要使用这些实例中的某个时,代理自动地选择某个实例返回

上面的例子中,我们的 Cart Bean 是一个接口,这是最为理想的代理模式,如果 Cart 是一个具体的类而不是一个接口,那么 Spring 就必须通过 CGLib 来生成基于类的代理,此时,我们要将 proxyMode 设置为 ScopedProxyMode.TARGET_CLASS,以此来表示要以生成目标类扩展的方式创建代理

 

 

 

Bean 在需要的时候由 Spring 装载到 Spring 应用上下文中,随着应用上下文而销毁:

  1. Spring 对 Bean 进行实例化
  2. Spring 将值和 Bean 引用注入到 Bean 对应的属性中
  3. 如果 Bean 类实现了 org.springframework.beans.factory.BeanNameAware 接口,则执行其setBeanName 方法
  4. 如果 Bean 类实现了 org.springframework.beans.factory.BeanFactoryAware 接口,则执行其setBeanFactory 方法
  5. 如果 Bean 类实现了 org.springframework.context.ApplicationContextAware 接口,则执行其setApplicationContext 方法
  6. 容器 中如 果有实现 org.springframework.beans.factory.BeanPostProcessors 接口的实例,则任何Bean在初始化之前都会执行这个实例的processBeforeInitialization 方法
  7. 如果 Bean 类实现了 org.springframework.beans.factory.InitializingBean 接口,则执行其afterPropertiesSet 方法
  8. 如果 Bean 使用了 init-method 声明初始化方法,Spring 调用该方法
  9. 如果 Bean 实现了 org.springframework.beans.factory.BeanPostProcessors 接口,则执行其 processAfterInitialization 方法
  10. 此时,bean 已经准备就绪,可以被应用程序使用,他们将一直驻留在应用上下文中,直到应用上下文被销毁
  11. 在容器关闭时,如果 Bean 类实现了 org.springframework.beans.factory.DisposableBean 接口,则执行它的 destroy 方法
  12. 如果 Bean 使用了 destroy-method 声明初始化方法,Spring 调用该方法

 

Bean 提供了初始化和销毁的方法,即 init-method 和 destroy-method 参数,分别在初始化 Bean 时和销毁 Bean 时调用:

<bean id="auditorium" class="com.techlog.test.dol.Auditorium" init-method="turnOnLights" destroy-method="turnOffLights"/>

 

 

如果你需要为每个 bean 都设置 init-method 或 destory-method 属性,那么,你可以在 <beans> 元素中统一设置 default-init-method 和 default-destory-method

 






读书笔记      技术帖      web      框架      龙潭书斋      技术分享      java      framework      spring      ioc      依赖注入      spring in action     


京ICP备15018585号