【Spring面试】二、BeanFactory与IoC容器的加载

文章目录

  • Q1、BeanFactory的作用是什么?
  • Q2、BeanDefinition的作用是什么?
  • Q3、BeanFactory和ApplicationContext有什么区别?
  • Q4、BeanFactory和FactoryBean有什么区别?
  • Q5、说下Spring IoC容器的加载过程(※)
  • Q6、Spring Ioc有哪些扩展点,在什么时候调用?

Q1、BeanFactory的作用是什么?

在这里插入图片描述

答案:

  • BeanFactory是Spring中非常核心的一个顶层接口(顶层即无父接口)
  • 它是Bean的工厂,主要职责就是生产Bean
  • 实现了简单工厂的设计模式,即通过调用getBean传入标识来生产一个Bean
  • 它有非常多的实现类,每个工厂都有不同的职责(单一职责功能),最强大的是DefaultListableBeanFactory,Spring底层就是使用该实现工厂来生产Bean的

在这里插入图片描述

Q2、BeanDefinition的作用是什么?

答案:

它主要负责存储Bean的定义信息,决定Bean的生产方式。如spring.xml:

<bean class="com.llg.User " id="user" scope="singleton" lazy="false" abstract="false" autowire="none" ><property name="username" value="9527">
</bean>

把以上Bean的这些定义信息,拿到并赋值给BeanDefinition(的实现类)的属性,然后交给BeanFactory来生产:

在这里插入图片描述

以汽车为例来对比:

在这里插入图片描述

Q3、BeanFactory和ApplicationContext有什么区别?

在这里插入图片描述

答案:

  • ApplicationContext即Spring的上下文,其实现了BeanFactory接口。

  • FactoryBean的getBean方法用于生产Bean,但ApplicationContext不生产Bean,而是通知FactoryBean来干活儿(即调用),它的getBean方法其实是个门面方法,底层在调BeanFactory的getBean方法

  • 它们都可以做为Spring容器,因为它们都可以来管理Bean的声明周期

  • ApplicationContext在开发中打交道最多,是因为它做了更多的事情,如自动把我们配置的Bean(如@Component)注册进来、加载环境变量、实现事件监听等

  • ApplicationContext和BeanFactory,就像4S店和汽车厂的关系,它虽然不造车,从车厂拿车,但它会做销售、保养、上牌等一系列事儿

Q4、BeanFactory和FactoryBean有什么区别?

答案:

  • BeanFactory是一个工厂,也是一个容器,用来管理和生产Bean的

  • FactoryBean则只是一个Bean,特殊的Bean,所以也是由BeanFactory来管理的

  • FactoryBean是一个接口,必须被另一个Bean去实现,此时这个被寄生的Bean则不再是是它自身,而是FactoryBean接口中getObject方法返回的那个Bean,getObject方法返回的这个Bean,可以是被寄生的Bean的子类,也可以是和被寄生的Bean的这个类毫无关系的类

  • 如果想获得原来的Bean实例,可加&

  • FactoryBean创建Bean的方式是懒加载的,使用Bean的时候才会调用getObject方法并把对象添加到容器

代码演示:

@Component
public class UserMapper{public UserMapper(){System.out.println("UerMapper对象加载");}public void query(){System.out.println("query");}
}
@Configuration
@ComponentScan  //扫不到时自己调整包路径
public class MainConfig{
}
public class Run{public static void main(String[] args){AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);UserMapper userMapper = (USerMapper) context.getBean("userMapper");userMapper.query();}}

此时运行一切正常:

在这里插入图片描述

UserMapper再去实现FactoryBean这个接口,此时getBean得到的userMapper对象就是重写的getObject方法返回的对象。

@Component
public class UserMapper implements FactoryBean{public UserMapper(){System.out.println("UerMapper对象加载");}public void query(){System.out.println("query");}@Overridepublic Object getObject() throws Exception{return "code9527";   //直接返回一个不相干的String对象}@Overridepublic Class<?> getObjectType(){return String.class;}
}

此时,getBean得到的userMapper就是一个String对象,那自然会类转换异常:

在这里插入图片描述

想获得原Bean,则加&:

UserMapper userMapper = (USerMapper) context.getBean("userMapper");

在这里插入图片描述

且此时创建Bean的方式是懒加载的,使用Bean的时候才会调用getObject方法并把对象添加到容器。修改下getObject:

在这里插入图片描述
此时断点,执行完new AnnotationConfigApplication(),即容器创建完成、Bean加载完成,控制台仍未输出"getObject调用===",即并未执行getObject()方法,直到getBean时才输出:

在这里插入图片描述

Q5、说下Spring IoC容器的加载过程(※)

在这里插入图片描述
在这里插入图片描述
图片链接:https://www.processon.com/view/link/5f15341b07912906d9ae8642

答案:

对照上图:

  • 实例化一个ApplicationContext对象(此时Bean还只是代码里的简单定义,即概念态的Bean)
  • 调用Bean工厂的后置处理器完成扫描
  • 循环解析扫描出来的类信息,看是否有@Component注解
  • 有则实例化一个BeanDefinition对象来存储接续出来的信息
  • 把实例化好的beanDefinition对象put到beanDefinitionMap中缓存起来,以便后面实例化bean(定义态的Bean)
  • 再次调用其他bean工厂的后置处理器
  • 当然spring还会干很多事情,比如国际化,比如注册BeanPostProcessor
  • 实例化Bean则是spring调用finishBeanFactorylnitialization方法来实例化单例的bean,实例化之前spring要做验证,需要遍历所有扫描出来的类,依次判断这个bean是否Lazy,是否prototype,是否abstract等
  • 如果验证完成spring在实例化一个bean之前需要推断构造方法,因为spring实例化对象是通过构造方法反射,故而需要知道用哪个构造方法
  • 推断完构造方法之后spring调用构造射实例代个对象,注意我这里说的是对象、对象、对象,这个时候对象已经实例化出来了,但是并不是一个完整的bean,最简单的体现是这个时候实例化出来的对象属性是没有注入的,所以不是一个完整的bean(纯净态的Bean)
  • Spring处理合并后的beanDefinition
  • 判断是否需要完成属性注入,如果需要,则注入
  • 判断Bean的类型,回调Aware接口
  • 调用生命周期回调方法
  • 如果需要代理则完成代理
  • put到单例池,bean创建完成,存到Spring容器中,IoC容器加载完成。(成熟态的Bean

Q6、Spring Ioc有哪些扩展点,在什么时候调用?

问题分析:

扩展点,即Spring Ioc在加载的过程中,其底层会对外提供很多的扩展接口或者一些钩子方法,当我们自己去实现这些接口时,Spring就会在特定的点,帮我们调用钩子方法,从而实现对Spring底层的扩展。

在这里插入图片描述

Spring有非常多的扩展接口,重点有:

A1: 执行BeanFactoryPostProcessor的postProcessBeanFactory方法

Spring提供了对BeanFactory进行操作的处理器BeanFactoryProcessor,简单来说就是获取容器BeanFactory,这样就可以在真正初始化bean之前对bean做一些处理操作。bean工厂的bean属性处理容器,说通俗一些就是可以管理我们的bean工厂内所有的beandefinition(未实例化)数据,可以随心所欲的修改属性。

简单来说就是在工厂里所有的bean被加载进来后但是还没初始化前,对所有bean的属性进行修改也可以add属性值。


/*** 作用: 在注册BeanDefinition的可以对beanFactory进行扩展* 调用时机: Ioc加载时注册BeanDefinition的时候会调用* 看接口的参数,看它把啥给你了,比如这里给了BeanFactory对象*/
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postprocessBeanFactory(ConfigurableListableBeanFactory beanFactor) throws BeansException {}
}

A2: BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法

/**
* 作用:动态注册BeanDefinition
* 调用时机: Ioc加载时注册BeanDefinition 的时候会调用
*/@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException (RootBeanDefinition beanDefinition = new RootBeanDefinition(Car.class);registry.registerBeanDefinition("car",beanDefinition);
}

A3: Bean生命周期的回调方法:初始化和销毁

InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。

public interface InitializingBean {void afterPropertiesSet() throws Exception;
}

实现DisposableBean接口,在这个Bean生命周期结束前调用destory()方法做一些收尾工作

public interface DisposableBean {void destroy() throws Exception;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/107062.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF——Control与Template理解

文章目录 一、前言二、控件三、模板3.1 DataTemplate3.2 ControlTemplate3.3 ContentPresenter 四、结语 一、前言 最近又翻看了下刘铁猛的《深入浅出WPF》&#xff0c;发现对模板章节中的部分内容有了更深的体会&#xff0c;所以写篇文扯扯。 文章标题是Control与Template&a…

掌动智能国产化测试工具的重要性与优势

在信息技术领域的快速发展下&#xff0c;对于软件和硬件产品的质量和性能要求也日益提高。同时针对信创要求&#xff0c;国产化测试工具在这个过程中发挥着重要的作用&#xff0c;不仅能够提升产品的可靠性和稳定性&#xff0c;还能够降低测试成本和提高测试效率。作为国内领先…

PBR纹理的10种贴图

PBR 是基于物理的渲染的首字母缩写。它试图通过模拟材料如何吸收和反射光&#xff0c;以模仿现实世界中的光流的方式产生视觉效果。最近的游戏引擎由于其逼真的效果而越来越多地使用 PBR 纹理。对于实时渲染&#xff0c;它们被认为是真实世界场景的最佳近似值。 推荐&#xff…

pyechart练习二:星巴克门店分布

一、概述 数据集&#xff1a;25601行13列 二、可视化 1、星巴克全球分布图 &#xff08;1&#xff09;普通地图 由于包或数据格式错误&#xff0c;地图无法显示区域颜色。 import pandas as pd from pyecharts.charts import * import pyecharts.options as opts df pd.r…

抖店产品曝光率低怎么解决?提高曝光、点击、转化的技巧,可收藏

我是王路飞。 我之前一直在强调&#xff0c;抖店的核心有且只有一个&#xff0c;就是选品。 店铺内的所有问题&#xff0c;都是产品的问题&#xff0c;而你的运营手段&#xff0c;黑科技等等&#xff0c;终究只是外力罢了&#xff0c;既没办法让你赚到钱&#xff0c;也对你个…

画流程图用什么软件好?安利这几款

画流程图用什么软件好&#xff1f;画流程图是一项非常重要的技能&#xff0c;它可以帮助我们更好地规划和管理工作流程&#xff0c;提高工作效率。在现代的企业中&#xff0c;流程图已经成为了不可或缺的一部分&#xff0c;它可以用来描述各种业务流程、流程控制、组织结构等等…

mysql技术文档--之与redo log(重做日志)庖丁解析-超级探索!!!

阿丹&#xff1a; 在刚开始写本文章的是还不太清楚要如何去细啃下这两个体系&#xff0c;在查阅资料的过程中。发现大厂阿里的庖丁解InnoDB系列&#xff0c;详细了的写了很多底层知识&#xff0c;于是基于这个这两个文章才有了阿丹的这篇文章。 整体认知&#xff1a; 在 MySQ…

Java特性之设计模式【抽象工厂模式】

一、抽象工厂模式 概述 抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式 在抽象工厂模式中&#xff0c;接口是…

改善客户体验应该从哪几个方面入手?

在为客户提供良好使用体验的同时&#xff0c;还在针对性的为他们制定个性化服务&#xff0c;大多数公司都知道提供良好的客户体验的重要性&#xff0c;&#xff0c;那么如何为客户提供最佳的体验呢&#xff1f; 为客户提供最佳的体验需要从以下几方面入手&#xff1a; 了解客…

【mysql】—— 函数的基本介绍

前言&#xff1a; MySQL是一种常用的关系型数据库管理系统&#xff0c;它提供了许多内置的函数来进行数据操作和处理。本期&#xff0c;我将给大家介绍的就是关于 “函数” 的相关知识&#xff01;&#xff01;&#xff01; 目录 &#xff08;一&#xff09;日期函数 &#…

定时任务执行脚本

1、编写bat脚本 将newman运行测试集的命令编写为bat脚本保存 2、设置定时任务 在计算机上右键->管理&#xff0c;在弹出菜单里的任务计划程序里创建定时任务配置执行

软件开发文档大全(项目管理、开发、实施、交付、评审、投标支撑)

前言&#xff1a; 在软件开发过程中&#xff0c;项目管理、开发、实施文档是至关重要的一部分。这些文档不仅为项目提供了清晰的规划和指导&#xff0c;还有助于确保项目按时、按质量完成。本文将详细介绍这些文档的内容及其在软件开发过程中的作用。 软件开发全文档获取&#…