跳到主要内容

IoC 详解 - Bean 的生命周期

  • Bean 的实例化过程
    Bean 的实例化过程

1. Bean 的实例化和属性设置

  • 在完成容器的启动阶段后,对于 BeanFactory 来说并不会马上实例化相应的 Bean 定义,此时容器仅仅拥有所有对象的 BeanDefinition 来保存实例化阶段将要用的必要信息。只有当请求方通过 BeanFactory 的 getBean() 方法 请求某个对象实例时,才会触发 Bean 实例化阶段的活动

  • BeanFactory 的 getBean()方法 可以被客户端对象显式调用,也可以在容器内部隐式的被调用
    隐式调用的两种情况:

    1. 对于 BeanFactory: 对象实例化通常采用延迟初始化方式,当对象A被请求而需要第一次实例化时,如果它依赖的对象B没有被实例化过,容器会先对对象A依赖的对象进行实例化,此时容器内部会首先实例化对象B以及所有被对象A依赖而还没有进行实例化的对象。(在容器内部调用 getBean(),对于请求方来说是隐式的)
    2. 对于 ApplicationContext: 启动后会实例化所有的 bean 定义,但在实现的过程中仍然遵循 Spring 容器实现流程的两个阶段,只是会在启动阶段的活动完成之后,紧接着调用注册到该容器的所有 bean 定义的实例化方法。
  • 容器采用“策略模式(Strategy Pattern)”来决定采用什么方式初始化 bean实例,通常可以通过反射或者 CGLIB 动态字节码生成来初始化相应的 bean 实例 或者动态生成其子类

  • 容器总不是直接通过 new 方式添加对象,而是通过 AOP 实现机制,创造了一个目标对象的代理对象(可以简单理解为目标对象的子类,要么具有相同功能,要么更加强大)

2. Aware 接口

  • 在经过实例化和属性设置后,容器会检查当前对象实例是否实现了一系列的以 Aware 命名结尾的接口定义,如果是,则将这些 Aware 接口定义中规定的依赖注入给当前的对象实例
  • Aware 接口种类:
    • 对于 BeanFactory:
      • org.springframework.beans.factory.BeanNameAware: 如果 Spring容器 检测到当前对象实例实现了该接口,会将该对象实例的bean定义对应的 beanName 设置到当前实例
      • org.springframework.beans.factory.BeanClassLoaderAware: 如果检测到该接口实现,会将对应加载当前 bean 的 ClassLoader 注入当前实例,默认使用加载 org.springframework.util.ClassUtils 类的Classloader
      • org.springframework.beans.factory.BeanFactoryAware: 如果检测到该接口实现,BeanFactory容器 会将自身设置到当前对象实例,这样当前对象实例就拥有了一个 BeanFactory容器 的引用,并且可以对这个容器内允许访问的对象进行访问
    • 对于 ApplicationContext:
      • org.springframework.context.ResourceLoaderAware: ApplicationContext 实现了 Spring 的 ResourceLoader接口。当检测到该接口实现,或将当前 ApplicationContext 自身设置到对象实例,同样使当前对象实例拥有了其所在 ApplicationContext容器 的引用
      • org.springframework.context.ApplicationEventPublisherAware: ApplicationContext 作为一个容器,同时还实现了 ApplicationEventPublisher 接口,这样它就可以作为 ApplicationEventPublisher 使用。检测到该接口实现,会将自身注入当前对象实例
      • org.springframework.context.MessageSourceAware: ApplicationContext 通过 MessageSource 接口提供国际化的信息支持(I18n,Internationalization)。接测到该接口实现,会将自身注入当前对象实例
      • org.springframework.context.ApplicationContextAware: 将自身注入

3. BeanPostProcessor

  • 与 BeanFactoryPostProcessor 会处理容器内所有符合条件的 BeanDefinition 类似,BeanPostProcessor 会处理容器内所有符合条件的实例化后的对象实例
  • BeanFactoryPostProcessor 在容器启动阶段,对象未创建之前对创建对象的 BeanDefinition 进行修改,而 BeanPostProcessor 通过 AOP 对一个已经生成的对象进行扩展
  • ApplicationContext 对应的 Aware接口 实例上就是通过 BeanPostProcessor 的方式进行处理的,当 ApplicationContext 中每个对象的实例化过程走到 BeanPostProcessor前置处理 这一步时,容器会检测到之前注册到容器的 ApplicationContextAwareProcessor(BeanPostProcessor 的实现类),然后调用其中的 postProcessBeforeInitialization()方法,检查并设置相关依赖
  • 将 BeanPostProcessor 注入到容器中:
    • BeanFactory: 手动写代码注入
      ConfigurableBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(...));
      beanFactory.addBeanPostProcessor(new PasswordDecodePostProcessor());
    • ApplicationContext: 通过配置文件
      <beans>
      <bean id="passwordDecodePostProcessor" class="package.name.PasswordDecodePostProcessor">
      <!--如果需要,注入必要的依赖-->
      </bean>
      </beans>

4. init-method

  • init-method 可以指定我们在容器中获得的对象在执行任何方法前,先执行此方法(比如做任何事情前先洗手)
    定义方式:
    <bean id="tradeDateCalculator" class="FXTradeDateCalculator" 
    init-method="setupHolidays">

5. destory-method

  • 与 init-method 相对应,定义在这个对象被销毁前,需要做的方法