Spring -- IOC 高级特性

一、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 的聚合过于紧密
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339

推荐阅读更多精彩内容