美文网首页
Spring -- IOC 高级特性

Spring -- IOC 高级特性

作者: Travis_Wu | 来源:发表于2021-02-17 15:02 被阅读0次

    一、lazy-Init 延迟加载(懒加载)

    • ApplicationContext 容器的默认行为是在启动服务器时将所有 singleton bean 提前进行实例化,提前实例化意味着作为初始化过程的⼀部分,ApplicationContext 实例会创建并配置所有的 singleton bean,比如:
      <!--lazy-init="false",立即加载,表示在 Spring 启动时,立刻进行实例化-->
      <bean id="testBean" class="com.wujun.LazyBean" />
      <!-- 该bean默认的设置为: -->
      <bean id="testBean" calss="com.wujun.LazyBean" lazy-init="false" />
      
    • 如果不想让⼀个 singleton bean 在 ApplicationContext 实现初始化时被提前实例化,那么可以将bean 设置为延迟实例化 <bean id="testBean" calss="com.wujun.LazyBean" lazy-init="true" />
      设置 lazy-init 为 true 的 bean 将不会在 ApplicationContext 启动时提前被实例化,而是第⼀次向容器通过 getBean 索取 bean 时实例化
    • 如果⼀个设置了立即加载的 bean1,引用了⼀个延迟加载的 bean2 ,那么 bean1 在容器启动时被实例化,而 bean2 由于被 bean1 引用,所以也被实例化,这种情况也符合延时加载的 bean 在第⼀次调用时才被实例化的规则
    • 也可以在容器层次中通过在 元素上使用 "default-lazy-init" 属性来控制延时初始化,如下面配置:
      <beans default-lazy-init="true">
         <!-- no beans will be eagerly pre-instantiated... -->
      </beans>
      
    • 如果⼀个 bean 的 scope 属性为 scope="pototype" 时,即使设置了 lazy-init="false",容器启动时也不会实例化 bean,而是调用 getBean 方法实例化的
    • 在类上使用注解 @Lazy 也可以开启延迟加载,默认值为 true,也就是说加了注解的类默认就是要开启延迟加载的类
    • 应用场景:
      1. 开启延迟加载⼀定程度提高容器启动和运转性能(当服务器内存差点意思的时候,可以使用延迟加载来优化,因为不是所有对象都要立即使用的)
      2. 对于不常使用的 Bean 设置延迟加载,这样偶尔使用的时候再加载,不必要从⼀开始该 Bean 就占用资源

    二、FactoryBean 和 BeanFactory

    • BeanFactory 接口是容器的顶级接口,定义了容器的⼀些基础行为,负责生产和管理 Bean 的⼀个工厂,通常使用它下面的子接口类型,比如 ApplicationContext
    • Spring 中 Bean 有两种,⼀种是普通Bean,⼀种是工厂Bean(FactoryBean),FactoryBean 可以生成某⼀个类型的 Bean 实例(返回给我们),也就是说我们可以借助于它自定义 Bean 的创建过程
    • FactoryBean 使用较多,尤其在 Spring 框架⼀些组件中会使用,还有其他框架和Spring 框架整合时使用
      // 可以让我们⾃定义Bean的创建过程(完成复杂 Bean 的定义)
      public interface FactoryBean<T> {
          // 返回 FactoryBean 创建的Bean实例,
          // 如果 isSingleton 返回 true,则该实例会放到Spring容器的单例对象缓存池中Map
          @Nullable
          T getObject() throws Exception;
          // 返回 FactoryBean 创建的 Bean 类型
          @Nullable
          Class<?> getObjectType();
          // 返回作用域是否单例
          default boolean isSingleton() {
              return true;
          }
      }
      

    三、后置处理器

    • 概念
      Spring 提供了两种后处理 bean 的扩展接口,分别为 BeanPostProcessor 和 BeanFactoryPostProcessor,两者在使用上是有所区别的
      1. 在 BeanFactory 初始化之后可以使用 BeanFactoryPostProcessor 进行后置处理做⼀些事情
      2. 在 Bean 对象实例化(并不是 Bean 的整个生命周期完成)之后可以使用 BeanPostProcessor 进行后置处理做⼀些事情,注意:对象不⼀定是 SpringBean,而 SpringBean ⼀定是个对象
    • SpringBean 的生命周期
      1. 根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean
      2. 利用依赖注入完成 Bean 中所有属性值的配置注入
      3. 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值
      4. 如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用
      5. 如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用
      6. 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的
      7. 如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法
      8. 如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法(如果使用 @PostConstruct 代替的话,@PostConstruct 所标注的方法执行顺序是在第6条之后,第7条之前的)
      9. 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization(),此时,Bean 已经可以被应用系统使用了
      10. 如果在 <bean> 中指定了该 Bean 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IOC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 <bean> 中指定了该 Bean 的作用范围为 scope="prototype",则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean
      11. 如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁,如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁
      12. 注意:Spring 为 Bean 提供了细致全面的生命周期过程,通过实现特定的接口或 <bean> 的属性设置,都可以对 Bean 的生命周期过程产生影响,虽然可以随意配置 <bean> 的属性,但是建议不要过多地使用 Bean 实现接口,因为这样会导致代码和 Spring 的聚合过于紧密

    相关文章

      网友评论

          本文标题:Spring -- IOC 高级特性

          本文链接:https://www.haomeiwen.com/subject/apuixltx.html