欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring IOC高级特性(lazy-Init 延迟加载,FactoryBean,后置处理器)

程序员文章站 2022-05-03 23:37:51
Spring IOC高级特性(lazy-Init 延迟加载,FactoryBean,后置处理器)文章内容输出来源:拉勾教育Java高薪训练营看前可以先阅读上一篇文章:详解Spring IOC1. lazy-Init 延迟加载Bean的延迟加载(延迟创建)ApplicationContext 容器的默认行为是在启动服务器时将所有 singleton bean 提前进行实例化。提前实例化意味着作为初始化过程的一部分,ApplicationContext 实例会创建并配置所有的singleton bea...

Spring IOC高级特性(lazy-Init 延迟加载,FactoryBean,后置处理器)



文章内容输出来源:拉勾教育Java高薪训练营


看前可以先阅读上一篇文章:详解Spring IOC

1. lazy-Init 延迟加载

Bean的延迟加载(延迟创建)

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

<!--该bean默认的设置为:--> <bean id="testBean" calss="cn.lagou.LazyBean" lazy-init="false" /> <!--开启延迟加载--> <bean id="testBean" calss="cn.lagou.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标签上的lazy-init比beans标签上的default-lazy-init优先级高。

lazy-Init 应用场景

  1. 开启延迟加载一定程度提高容器启动和运转性能

  2. 对于不常使用的 Bean 设置延迟加载,这样偶尔使用的时候再加载,不必要从一开始该 Bean 就占用资源

2. FactoryBean 和 BeanFactory

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

此处我们重点分析FactoryBean: Spring中Bean有两种,一种是普通Bean,一种是工厂Bean(FactoryBean),FactoryBean可以生成

某一个类型的Bean实例(返回给我们),也就是说我们可以借助于它自定义Bean的创建过程。

Bean创建的三种方式中的静态方法和实例化方法和FactoryBean作用类似,FactoryBean使用较多,尤其在Spring框架一些组件中会使用,还有其他框架和Spring框架整合时使用。

// 可以让我们自定义Bean的创建过程(完成复杂Bean的定义)  public interface FactoryBean<T> { // 返回FactoryBean创建的Bean实例,如果isSingleton返回true,则该实例会放到Spring容器 的单例对象缓存池中Map @Nullable T getObject() throws Exception; // 返回FactoryBean创建的Bean类型 Class<?> getObjectType(); // 返回作用域是否单例 @Nullable default boolean isSingleton() { return true; } } 

举个例子

//需要借助工厂Bean创建的Bean package com.lagou.edu.pojo; public class Company { private String name; private String address; private int scale; ...省略get、set方法和toString方法 } 
package com.lagou.edu.factory; import com.lagou.edu.pojo.Company; import org.springframework.beans.factory.FactoryBean; public class CompanyFactoryBean implements FactoryBean<Company> { // 公司名称,地址,规模 private String companyInfo; public void setCompanyInfo(String companyInfo) { this.companyInfo = companyInfo; } // 模拟创建复杂对象Company @Override public Company getObject() throws Exception { Company company = new Company(); String[] strings = companyInfo.split(","); company.setName(strings[0]); company.setAddress(strings[1]); company.setScale(Integer.parseInt(strings[2])); return company; } //获得创建Bean的类型 @Override public Class<?> getObjectType() { return Company.class; } //获得是否是单例模式 @Override public boolean isSingleton() { return true; } } 
//xml中配置 <bean id="companyBean" class="com.lagou.edu.factory.CompanyFactoryBean"> <property name="companyInfo" value="拉勾,中关村,500"/> </bean> 
//测试获取FactoryBean产生的对象 Object companyBean = applicationContext.getBean("companyBean"); System.out.println("bean:" + companyBean); //结果如下 bean:Company{name='拉勾', address='中关村', scale=500} --------------------------------- //获取FactoryBean,需要在id之前添加“&” Object companyBean = applicationContext.getBean("&companyBean"); System.out.println("bean:" + companyBean); // 结果如下  bean:com.lagou.edu.factory.CompanyFactoryBean@53f6fd09 

3. 后置处理器

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

工厂初始化(BeanFactory)—> Bean对象

BeanFactory初始化之后可以使用BeanFactoryPostProcessor进行后置处理做一些事情

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

注意:对象不一定是springbean,而springbean一定是个对象

3.1 BeanPostProcessor

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

//源码 //定义一个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进行处理。 //如果要对具体的某个bean处理,可以通过方法参数判断,两个类型参数分别为Object和String //第一个参数是每个bean的实例,第二个参数是每个bean的name或者id属性的值。 public interface BeanPostProcessor { //在Bean的初始化方法前执行,具体这个初始化方法指的是什么方法,类似我们在定义bean时,定义了init-method所指定的方法 @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; } } 

3.2 BeanFactoryPostProcessor

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

//源码 @FunctionalInterface public interface BeanFactoryPostProcessor { void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException; } //此接口只提供了一个方法,方法参数为ConfigurableListableBeanFactory,该参数类型定义了一些方法 //其中有个方法名为getBeanDefinition的方法,我们可以根据此方法,找到我们定义bean的BeanDefinition对象。然后我们可以对定义的属性进行修改。 //BeanDefinition中的方法名字类似我们bean标签的属性,setBeanClassName对应bean标签中的class属性,所以当我们拿到BeanDefinition对象时,我们可以手动修改bean标签中所定义的属性值。 

BeanDefinition对象: 我们在 XML 中定义的 bean标签,Spring 解析 bean 标签成为一个 JavaBean,这个JavaBean就是BeanDefinition

注意:调用 BeanFactoryPostProcessor 方法时,这时候bean还没有实例化,此时 bean 刚被解析成 BeanDefinition对象。

本文地址:https://blog.csdn.net/weixin_43871142/article/details/108254133