【Java Spring基本问题】记录面试题宝典中自己不熟悉的Spring问题
创始人
2025-06-01 09:01:23
0

文章目录

  • Spring Bean定义装配
  • Spring Bean生命周期
  • Spring Bean容器
  • Spring 循环依赖
  • Spring 事务
  • @Autowired和@Resource

Spring Bean定义装配

参考文章
1. 定义Spring Bean的三种方式
XML文件定义Spring Bean

JavaConfig定义Spring Bean

@Component注解定义SpringBean

2. 装配Spring Bean的四种方式
手动装配 + XML文件

自动装配 + XML文件

手动装配 + JavaConfig文件

自动装配 + 注解

Spring Bean生命周期

参考文章:Bean的生命周期(不要背了记思想)
参考文章:Bean流程非常详细
Bean注册
调用各种BeanDefinitionReader读取各种配置来源信息,并将其转化为BeanDefintion的过程。

Bean实例化
调用Spring Bean的构造器实例化

Bean属性注入
调用postProcessPropertyValues方法,对Spring Bean属性注入
调用一系列Aware接口的实现类,获取Bean的属性(BeanName、BeanFactory等等)

Bean初始化调用的init-method属性指定的初始化方法
调用初始化前方法postProcessBeforeInitialization
调用InitializingBean.afterPropertiesSet属性设置后方法
调用初始化后方法postProcessAfterInitialization

Bean销毁
调用DiposibleBean.destory()

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {// Instantiate the bean. 实例化beanBeanWrapper instanceWrapper = null;.....if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}.....boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}//添加到三级缓存中addSingletonFactory(beanName, new ObjectFactory() {@Overridepublic Object getObject() throws BeansException {return getEarlyBeanReference(beanName, mbd, bean);}});}// Initialize the bean instance.Object exposedObject = bean;try {// 填充属性populateBean(beanName, mbd, instanceWrapper);if (exposedObject != null) {// 初始化BeanexposedObject = initializeBean(beanName, exposedObject, mbd);}}......return exposedObject;}
 

Spring Bean容器

Spring主要提供了两种类型的容器:BeanFactory和ApplicationContext

1. BeanFactory
使用示例

XmlBeanFactory factory = new XmlBeanFactory (new ClassPathResource("beans.xml")); 
HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");  

2. ApplicationContext
使用示例

ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); 
HelloWorld obj = (HelloWorld) context.getBean("helloWorld"); 

3. 两者区别

1. ApplicationContext,继承于BeanFactory,是相对比较高级的容器实现。
2. BeanFactory在启动的时候不会去实例化Bean,ApplicationContext在启动的时候就把所有的Bean全部实例化了

Spring 循环依赖

1. Spring循环依赖的三种情况
构造器的循环依赖:无法处理

非单例Bean循环依赖:无法处理

单例Bean循环依赖:使用三级缓存处理

2. 单例Bean循环依赖的解决
使用三级缓存

// 完成初始化的单例Bean
private final Map singletonObjects = new ConcurrentHashMap<>(256);// 完成实例化但是尚未填充属性和初始化的单例Bean
private final Map> singletonFactories = new HashMap<>(16);// 完成实例化但是尚未填充属性和初始化的单例Bean,并在这里发生AOP后置处理
private final Map earlySingletonObjects = new HashMap<>(16);

三级缓存解决循环依赖

  1. Spring 创建 bean 主要分为两个步骤,创建原始 bean 对象,接着去填充对象属性和初始化
  2. 每次创建 bean 之前,我们都会从缓存中查下有没有该 bean,因为是单例,只能有一个
  3. 当我们创建 beanA 的原始对象后,并把它放到三级缓存中,接下来就该填充对象属性了,这时候发现依赖了 beanB,接着就又去创建 beanB,同样的流程,创建完 beanB 填充属性时又发现它依赖了 beanA,又是同样的流程,不同的是,这时候可以在三级缓存中查到刚放进去的原始对象 beanA,所以不需要继续创建,用它注入 beanB,完成 beanB 的创建
  4. 既然 beanB 创建好了,所以 beanA 就可以完成填充属性的步骤了,接着执行剩下的逻辑,闭环完成

为什么需要三级缓存呢,二级他也够了呀
三级缓存就是为了后置处理,也就是说你不需要后置处理的话,那就不需要三级缓存,直接二级缓存就可以解决循环依赖。

那为什么二级缓存中不可以进行后置处理
假设我们现在是二级缓存架构,创建 A 的时候,我们不知道有没有循环依赖,所以放入二级缓存提前暴露,接着创建 B,也是放入二级缓存,这时候发现又循环依赖了 A,就去二级缓存找,是有,但是如果此时还有 AOP 代理呢,我们要的是代理对象可不是原始对象,这怎么办,只能改逻辑,在第一步的时候,不管3721,所有 Bean 统统去完成 AOP 代理,如果是这样的话,就不需要三级缓存了,但是这样不仅没有必要,而且违背了 Spring 在结合 AOP 跟 Bean 的生命周期的设计。

3. 无法解决循环依赖的场景
1. 构造器的循环依赖
将已经实例化但未完成属性填充的Bean放在三级缓存中,可以解决循环依赖的问题,但是如果是构造器的循环依赖,那么Bean连第一步的实例化都无法完成,即构造器无法执行。

2. 非单例Bean的循环依赖
因为 Spring 容器不进行缓存 prototype 作用域的 bean ,因此无法提前暴露一个创建中的bean 。

Spring 事务

1. 声明式事务和编程式事务
声明式事务就是通过注解即配置的方式进行事务的管理
编程式事务就是自己在业务逻辑种编写代码来管理事务

2. 7种事务传播行为
参考文章:事务传播行为

@Transactional(propagation = Propagation.REQUIRES_NEW)

在这里插入图片描述

@Autowired和@Resource

1. @Autowired和@Qualifier

public class Pepole {private String name;
//1. 通过名字装配@Autowired@Qualifier("books1")private Books books;
//2. 通过类型装配@Autowiredprivate Hobbies hobbies;
}

在这里插入图片描述
2. @Resource

// @Resource指定按type自动装配@Resource(type = Books.class)private Books books;// @Resource指定按name自动装配@Resource(name = books)private Books books;

在这里插入图片描述

相关内容

热门资讯

最新或2023(历届)做错事检... 篇一:  检讨书  尊敬的办主任:  怀着对您深深的歉意和无比的愧疚写下这份检讨书,我对我的过错做深...
因为上课说话的检讨书范文 上课... 因为上课说话的检讨书一:  尊敬的班主任老师:  我上课时候说话是犯了严重的纪律错误,身为一名学生,...
最新或2023(历届)财务工作...  范文一  尊敬的公司领导:  您好,在此向您递交这份关于我财务工作疏忽的说明以及相关检讨,以表达我...
财务管理失职检讨书最新 财务工... 【篇一】管理失职检讨书  酒店领导:  我怀着自责、反省和感激的心情写这份检讨书,在单位3年的日子里...
最新或2023(历届)财务工作...  尊敬的公司领导:  您好,在此向您递交这份关于我财务工作疏忽的说明以及相关检讨,以表达我对自己财务...
最新或2023(历届)校园打架... 最新或2023(历届)校园检讨书范文一:  尊敬的学校政教处老师:  非常抱歉地向您递交我打架斗殴的...
最新或2023(历届)学生逃课...   学生逃课的检讨书最新或2023(历届)一:  尊敬的辅导员:  您好!  对于这次的逃课事件,我...
最新或2023(历届)财务人员...  尊敬的公司领导:  身为一名工作2年的财务人员,本职工作性质所在,工作的重中之重就是确保好资金安全...
最新或2023(历届)考试带手... 最新或2023(历届)考试带手机检讨书【篇一】  亲爱的班主任,敬爱的吴老师:  我是xx中学高二x...
带手机去学校检讨书精选 手机检... 带手机去学校检讨书【篇一】  我是你的学生:XXX.今天我怀着愧疚和懊悔给您写下这份检讨书,以向您表...
最新或2023(历届)春节放假... 春节放假的通知最新或2023(历届)最新预测版  最新或2023(历届)2月7日至最新或2023(历...
遮娄其王朝是如何灭亡的?是被谁... 753年,遮娄其王朝的一名封臣丹蒂杜尔加崛起,推翻了超日王二世的继承人,莫定了拉喜特拉库塔帝国的基石...
清朝螳螂拳的创始人于七,有哪些... 崂山华严寺坐落在王哥庄镇返岭后村西那罗延山上,是崂山中现存的唯一佛寺。明崇祯末年,84岁的慈沾住持圆...
遮娄其王朝有着怎样的特点?疆域... 拉什特拉库特取代了遮娄其的地位,称霸南印度达两个世纪。公元三世纪起,贵霜帝国逐渐衰落,北印度重新分裂...
于七是什么人?清朝于七生平简介... 于七, 汉族。 顺治十六年(公元1659)年,郑成功为了恢复明王朝,挥师抗清,激发了北方各地农民的起...
遮娄其王朝有着怎样的特点?疆域... 拉什特拉库特取代了遮娄其的地位,称霸南印度达两个世纪。公元三世纪起,贵霜帝国逐渐衰落,北印度重新分裂...
丁朝到底有多少兵力?真的有传说... 刑律丁部领开国后不久,便采用严刑,欲“威制天下”。乃于朝廷上设置大鼎(即油锅),以及饲养猛虎,在国内...
丁朝:越南地区从中国正式独立后... 丁朝(越南语:Nhà ?inh;时间:968─980年),是越南的封建朝代,也是越南地区从中国正式独...
丁朝到底有多少兵力?真的有传说... 刑律丁部领开国后不久,便采用严刑,欲“威制天下”。乃于朝廷上设置大鼎(即油锅),以及饲养猛虎,在国内...
植树造林倡导书范文 植树造林倡... 植树造林倡导书范文  植树造林是保护环境的重要组成部分,树木是我们的朋友,能给我们人类提供很多帮助,...