Spring面试题

1. 说说你对Spring的理解

  • Spring是一个轻量级的java开发框架,旨在提高开发人员的开发效率和系统的可维护性
  • 主要包括spring core、spring beans、spring context、spring jdbc、spring aop、spring Web、spring test等模块
  • 核心就是IOC和AOP,即控制反转和面向切面编程

Spring的优点

  • 简化开发,方便解耦;
  • 支持AOP编程和声明式事务;
  • 方便程序测试和集成优秀框架。

Spring的缺点

  • Spring依赖反射,影响性能,学习入门时间较长。

2. 谈谈你对IOC和AOP的理解

  • IOC即控制反转是一种设计思想,就是把对象的控制权交给框架来管理;其中最主要就是通过依赖注入来管理对象;极大的降低了代码量和对象之间是耦合性;其实现机制就是工厂模式和反射机制。
    为什么spring会降低耦合性
  • AOP即面向切面编程,就是不改变原有业务的基础上,对业务方法进行增强。简单说就是那些与业务无关,却被业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。其实现机制就是动态代理。

3. 解释bean的生命周期

前言
面试中经常会被问到Spring Bean的生命周期,有些人说记不住,看了一遍源码也是云里雾里的,那是因为只看理论,没有自己实践,如果自己亲自写代码验证一下,不管是对Spring的宏观感受,还是微观的感觉,都会有进一步的理解。
本篇会先展示代码的结果,后面再进行分析,代码的获取地址:代码
1、测试结果演示

Spring容器初始化===========================
五月 16, 2020 3:18:44 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@13b6d03: startup date [Sat May 16 15:18:44 CST 2020]; root of context hierarchy
五月 16, 2020 3:18:45 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
【步骤1】执行Bean的无参构造函数
【步骤2】执行Bean的set方法,设置name属性值:coolsummermoon
【步骤2】执行Bean的set方法,设置sex属性值:man
【步骤3】执行BeanNameAware中setBeanName方法,beanName值:iocBeanLifeService
【步骤4】执行BeanClassLoaderAware中setBeanClassLoader,ClassLoader的name = sun.misc.Launcher$AppClassLoader
【步骤5】执行BeanFactoryAware中setBeanFactory,beanFactory中是否包含IocBeanLifeService:true
【步骤6】执行EnvironmentAware的setEnvironment方法
【步骤7】执行ResourceLoaderAware的setResourceLoader方法,Resource File Name=applicationContext.xml
【步骤8】执行ApplicationEventPublisherAware中setApplicationEventPublisher方法
【步骤9】执行ApplicationContextAware的setApplicationContext方法,Bean Definition Names=[iocBeanLifeService, org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0, ioc.CustomerBeanPostProcessor#0]
【步骤10】执行BeanPostProcessor中postProcessBeforeInitialization方法,beanName=iocBeanLifeService
【步骤11】执行PostConstruct注解标注的方法
【步骤12】执行InitializingBean的afterPropertiesSet方法
【步骤13】执行配置的init-method
【步骤14】执行BeanPostProcessor的postProcessAfterInitialization方法,beanName=iocBeanLifeService
五月 16, 2020 3:18:45 下午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@13b6d03: startup date [Sat May 16 15:18:44 CST 2020]; root of context hierarchy
Spring容器初始化完毕========================
从容器中获取Bean
IocBeanLifeService{name='coolsummermoon', sex='man'}
Spring容器准备关闭==========================
【步骤15】执行preDestroy注解标注的方法
【步骤16】执行DisposableBean接口的destroy方法
【步骤17】执行配置的destroy-method
Spring容器完成关闭===========================
Process finished with exit code 0

2、结果分析
2.1、上面的结果,我们可以初步分四个阶段:

  1. Bean的实例化阶段
  2. Bean的设置属性阶段
  3. Bean的 初始化阶段
  4. Bean的销毁阶段

2.2、在初始化阶段,有个特别重要的接口BeanPostProcessor,在初始化前、后调用:
在这里插入图片描述
2.3、在设置属性阶段后,postProcessBeforeInitialization方法执行前,会执行很多Aware类型的接口,这种类型接口作用是加载资源到Spring容器中,Aware前面的名字就对应哪种资源,依次加载的是:

  1. BeanNameAware
  2. BeanClassLoaderAware
  3. BeanFactoryAware
  4. EnvironmentAware
  5. ResourceLoaderAware
  6. ApplicationEventPublisherAware
  7. ApplicationContextAware

看到这里应该明白BeanFactory和ApplicationContext的区别了:
BeanFactoryAware之前加载的资源都是公共的。BeanFactoryAware后面加载的资源都是ApplicationContext独有的。

2.4、初始化方式有三个,分别是:

  1. InitializingBean的afterPropertiesSet方法
  2. PostConstruct注解标注的方法
  3. 配置的init-method

上面的三个方法效果都是一样的,开发中选择其中一种方式就行,一般我们选择2、3方法中的一个。

2.5、容器销毁的方式有三个,分别是:

  1. preDestroy注解标注的方法
  2. DisposableBean接口的destroy方法
  3. 配置的destroy-method

上面的三个方法效果都是一样的,开发中选择其中一种方式就行,一般我们选择1、3方法中的一个。

3、总结
综合前面的代码和分析,现在我们用大白话描述下:

  1. Bean容器找到Spring配置文件中Bean的定义;
  2. Bean容器利用java 反射机制实例化Bean;
  3. Bean容器为实例化的Bean设置属性值;
  4. 如果Bean实现了BeanNameAware接口,则执行setBeanName方法;
  5. 如果Bean实现了BeanClassLoaderAware接口,则执行setBeanClassLoader方法;
  6. 如果Bean实现了BeanFactoryAware接口,则执行setBeanFactory方法;
  7. 如果 ……真的,到这我经常忘记,但前面三个Aware接口肯定能记住;
  8. 如果Bean实现了ApplicationContextAware接口,则执行setApplicationContext方法;
  9. 如果加载了BeanPostProcessor相关实现类,则执行postProcessBeforeInitialization方法;
  10. 如果Bean实现了InitializingBean接口,则执行afterPropertiesSet方法;
  11. 如果Bean定义初始化方法(PostConstruct注解或者配置的init-method),则执行定义的初始化方法;
  12. 如果加载了BeanPostProcessor相关实现类,则执行postProcessAfterInitialization方法;
  13. 当要销毁这个Bean时,如果Bean实现了DisposableBean接口,则执行destroy方法。
  14. 当要销毁这个Bean时,如果自定义了销毁方法(PreDestroy注解或者配置destroy-method),则执行定义的销毁方法。

参考地址链接:spring的bean生命周期详解

4. Spring的启动流程(IOC容器的启动流程)

  1. 初始化Spring容器
  2. 将配置类的BeanDefinition注册到容器中
  3. refresh()是AbstractApplicationContext类中的模板方法,其定义了容器启动的主要流程:
    1. 进行环境的准备,包括Context的启动时间,活动状态等等;
    2. 创建BeanFactory容器,并设置基础属性
    3. 加载配置文件,解析bean的定义信息,包装成Beandefinition。
    4. 执行BeanFactoryPostProcess,对BeanFactory的相关信息进行扩展。
    5. 实例化对象
    6. 填充属性
    7. 初始化对象
    8. 获取对象

5. 循环依赖

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值