Spring 常考问题整理(三)

6. Spring Bean 的生命周期

Spring Bean 的生命周期可以分为四个大阶段:

  • 实例化
  • 属性赋值
  • 初始化
  • 销毁

具体步骤如下:

  1. 实例化 Bean:
    对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。
    对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。
  2. 设置对象属性:实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成属性设置与依赖注入。
  3. 处理 Aware 接口:Spring会检测该对象是否实现了xxxAware接口,通过Aware类型的接口,可以让我们拿到Spring容器的一些资源:
    ①如果这个Bean实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,传入Bean的名字; ②如果这个Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。 ②如果这个Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的是Spring工厂自身。 ③如果这个Bean实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文;
  4. BeanPostProcessor 前置处理:如果想对Bean进行一些自定义的前置处理,那么可以让Bean实现了BeanPostProcessor接口,那将会调用postProcessBeforeInitialization(Object obj, String s)方法。
  5. InitializingBean : 如果Bean实现了InitializingBean接口,执行afeterPropertiesSet()方法。
  6. init-method :如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。
  7. BeanPostProcessor 后置处理:如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法;由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;

以上几个步骤完成后,Bean就已经被正确创建了,之后就可以使用这个Bean了。

  1. DisposableBean:当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;
  2. destroy-method:如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。

7. Spring 中 bean 的作用域:

  1. singleton:默认作用域,单例,即每个容器中只会生成一个 bean 的实例;
  2. prototype:原型,为每一个bean 的请求都会创建一个新的实例;
  3. request:web 模式下的特性,为每一个 request 请求创建一个实例,在请求完成后 ,bean 会失效被GC回收;
  4. session:web模式下的特性,同一个 session 会话可以共享一个 bean 实例,不同的 session 会话使用不同的实例;
  5. global-session:全局作用域,所有会话共享一个实例。如果想要声明让所有会话共享的存储变量的话,那么这全局变量需要存储在global-session中。比如统计整个站点的在线人数等问题;

8. spring中的bean是线程安全的吗?

先说答案:Spring 不保证 bean 的线程安全, spring 的bean 线程安全取决于不同的条件。

spring 中的 bean 的默认作用域是 singleton,所以多个线程抢占同一个 bean 的使用权,肯定会出问题的;

把 spring 的 bean 作用域改为 prototype 后,就是单个线程操作一个 bean ,所以又不会出现线程安全问题;

但是有一些 bean 是无状态的,(不同的线程不会对这个bean 进行查询以外的操作,即不会存在说修改属性等)那么这个单例的 bean 就是线程安全的,比如 Conroller 类, Service 和 DAO;

那么如何解决有状态的 bean 的线程安全问题呢?

  1. 最浅显的解决办法就是将有状态的bean的作用域由singleton改为prototype
  2. 采用ThreadLocal解决线程安全问题,为每个线程提供一个独立的变量副本,不同线程只操作自己线程的副本变量。(关于 ThreadLocal 需要补课的小伙伴请自行补课,后期我也会出相关的知识点总结,一起学习,一起进步)。

9. Spring基于xml注入bean的几种方式:

  1. 构造注入(通过 index,通过类型)
  2. set 注入(需要显式定义 setter 方法)
  3. 静态工厂注入;
  4. 实例工厂;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

静香是个程序媛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值