Spring-IOC 高级特性

1. lazy-Init 延迟加载

  ApplicaitonContext 容器的默认行为是在启动时将所有 singleton bean 提前进行实例化。提前实例化意味着作为初始化过程的一部分,ApplicationContext 实例会创建所有的singleton bean

开启方式:

  • xml  :<bean id="xx" class="xx.xx.xx" lazy-init="true"> (特别:可以在<beans default-lazy-init="true"></beans>来全局配置)
  • anno:@Lazy

开启延迟加载后,bean 将不会在ApplicationContext启动时提前被实例化,而是在第一次向容器发起getBean调用索取bean时实例化

应用场景: 

 

  1. 开启延迟加载一定程度提高了容器启动和运转性能(现代设备性能提升,影响逐渐变小)
  2. 对于不常使用的 Bean设置延迟加载,这样偶尔使用的时候在加载,不必要从一开始该Bean 就占用资源 (更多是基于这个考虑)

2. FactoryBean 和 BeanFactory

  BeanFactory 接口是容器的顶级接口,定义了容器的一些基础行为,负责生产和管理Bean 的一个工厂,具体使用它下面的子接口类型,比如:ApplicationContext

  这里重点介绍FactoryBean:Spring 中的Bean 有两种,一种是普通 Bean ,一种是工厂 Bean(FactoryBean),FactoryBean 可以生成某一个类型的Bean实例(返回给我们),也就是说我们可以借助于它自定义 Bean 的创建过程。

FactoryBean接口:

/**
 * 可以让我们⾃定义Bean的创建过程(完成复杂Bean的定义)
 * @param <T>
 */
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;
    }
}

3. 后置处理器

  Spring 提供了两种后处理器 bean的扩展接口,分别为 BeanPostProcessor 和 BeanFactoryPostProcessor,两者在使用上是有所区别的

  顺序:工厂初始化 -> Bean 对象实例化

  在BeanFactory 初始化之后可以使用BeanFactoryPostProcessor 进行后置处理一些操作

  在 Bean 对象实例化(并不是Bnan的整个生命周期完成)之后可以使用BeanPostProcessor 进行后置处理做一些操作

  注: 对象不一定是springBean,而springBean一定是对象

BeanPostProcessor 

  BeanPostProcessor 是针对Bean 级别的处理,可以针对某个具体的Bean

  接口:

public interface BeanPostProcessor {

  /**
   * Bean 的初始化方法之前
   */ @Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; }
  /*
   * Bean 的初始化方法之后
   */ @Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }

定义一个类实现BeanPostProcessor ,默认是会对整个spring容器中所有的bean进行处理,如果要对具体的某个bean处理,可以通过方法参数(第一个参数是bean实例,第二个参数是每个bean的id或name属性值)判断。

注意:处理是发生在spring容器实例化和依赖注入之后

BeanFactoryPostProcessor 

  BeanFactory 级别的处理,是针对整个Bean的工厂进行处理,典型应用:

PropertyPlaceholderConfigurer。
接口:
@FunctionalInterface
public interface BeanFactoryPostProcessor {

    /**
     * 只有一个方法,参数为:ConfigurableListableBeanFactory 
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
此接⼝只提供了⼀个⽅法,⽅法参数为ConfifigurableListableBeanFactory,该参数类型定义了⼀些⽅法
其中有个方法名为:getBeanDefinition的方法,我们可以根据此方法,找到我们定义bean的BeanDefinition对象。然后我们可以对定义的属性进行修改。
BeanDefinition对象
  spring加载类对象,将类对象处理得到一个JavaBean(封装对象信息),这个JavaBnan 就是BeanDefinitioin对象
 
注意:调用BeanFactoryPostProcessor 方法式,这个时候bean还没有实例化,此时bean刚被处理成BeanDefinition对象



附:spring生命周期

注:图中6、7即对应为BeanPostProcessor 的两个方法

过程描述:

  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 属性指定了初始化⽅法,则调⽤该初始化⽅法。
  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 进⾏销毁。
 
注意:Spring 为 Bean 提供了细致全⾯的⽣命周期过程,通过实现特定的接⼝或 <bean> 的属性设置,都可以对 Bean 的⽣命周期过程产⽣影响。虽然可以随意配置 <bean> 的属性,但是建议不要过多地使⽤ Bean 实现接⼝,因为这样会导致代码和 Spring 的聚合过于紧密

 

posted on 2020-07-31 21:48  未知不知  阅读(296)  评论(0)    收藏  举报