Spring -- IOC 高级特性

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

  • ApplicationContext 容器的默认行为是在启动服务器时将所有 singleton bean 提前进行实例化,提前实例化意味着作为初始化过程的⼀部分,ApplicationContext 实例会创建并配置所有的 singleton bean,比如:
    
    
    
    
    
  • 如果不想让⼀个 singleton bean 在 ApplicationContext 实现初始化时被提前实例化,那么可以将bean 设置为延迟实例化
    设置 lazy-init 为 true 的 bean 将不会在 ApplicationContext 启动时提前被实例化,而是第⼀次向容器通过 getBean 索取 bean 时实例化
  • 如果⼀个设置了立即加载的 bean1,引用了⼀个延迟加载的 bean2 ,那么 bean1 在容器启动时被实例化,而 bean2 由于被 bean1 引用,所以也被实例化,这种情况也符合延时加载的 bean 在第⼀次调用时才被实例化的规则
  • 也可以在容器层次中通过在 元素上使用 "default-lazy-init" 属性来控制延时初始化,如下面配置:
    
       
    
    
  • 如果⼀个 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 {
        // 返回 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 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IOC 的缓存池中,将触发 Spring 对该 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 实现接口,因为这样会导致代码和 Spring 的聚合过于紧密

你可能感兴趣的:(Spring -- IOC 高级特性)