Spring 面试题(部分)
一、Spring 框架的优点有哪些?
轻量:Spring 框架是轻量级的,基本的版本大约 2MB;
容器:Spring 容器包含并管理应用中对象的生命周期和配置;
控制反转:通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们;
面向切面的编程(AOP):支持面向切面的编程,并且把应用业务逻辑和系统服务分开;
事务管理:提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA);
MVC 框架:Spring 的 WEB 框架是个精心设计的框架,是 Web 框架的一个很好的替代品;
异常处理:Spring 提供方便的 API 把具体技术相关的异常(比如由 JDBC,Hibernate or JDO 抛出的)转化为一致的 unchecked 异常。
二、IOC 和 DI 分别指的是什么?
控制反转,也就是把对象的创建、初始化、销毁交给 spring 容器来管理,而不是由开发者控制,实现控制反转。org.springframework.beans 和 org.springframework.context 包是 Spring Framework 的 IoC 容器的基础。实际项目中的 IOC 容器使用 ApplicationContext 接口实现。
依赖注入,在对象创建的过程中,动态的将对象依赖自动注入到调用该依赖的 Bean 对象中。
三、BeanFactory 接口和 ApplicationContext 接口有什么区别?
①Spring 核心工厂是 BeanFactory,它是所有容器的父接口,定义了容器操作各类对象的机制和方法。BeanFactory 采取延迟加载,第一次 getBean 时才会初始化 Bean。
②ApplicationContext 接口继承 BeanFactory 接口,ApplicationContext 是对 BeanFactory 扩展,它可以进行国际化处理、事件传递和 bean 自动装配以及各种不同应用层的 Context 实现。ApplicationContext 是会在加载配置文件时初始化 Bean。开发中基本都在使用 ApplicationContext,web 项目使用 WebApplicationContext ,很少用到 BeanFactory。
四、解释 Bean 的作用域
Spring 容器中的 bean 可以分为 5 个范围。
singleton:bean 范围是默认的,这种范围确保不管接受到多少个请求,每个容器中只有一个 bean 的实例,单例的模式由 bean factory 自身来维护。
prototype:原形范围与单例范围相反,为每一个 bean 请求提供一个实例。
request:在请求 bean 范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean 会失效并被垃圾回收器回收。
Session:与请求范围类似,确保每个 session 中有一个 bean 的实例,在 session 过期后,bean 会随之失效。
global-session:global-session 和 Portlet 应用相关。当你的应用部署在 Portlet 容器中工作时,它包含很多 portlet。如果你想要声明让所有的 portlet 共用全局的存储变量的话,那么这全局变量需要存储在 global-session 中。全局作用域与 Servlet 中的 session 作用域效果相同。
五、Spring 框架中的单例 Beans 是线程安全的么?
Spring 框架并没有对单例 bean 进行任何多线程的封装处理。关于单例 bean 的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的 Spring bean 并没有可变的状态(比如 Serview 类和 DAO 类),所以在某种程度上说 Spring 的单例 bean 是线程安全的。如果你的 bean 有多种状态的话(比如 View Model 对象),就需要自行保证线程安全。
实际上,是非线程安全的。
最浅显的解决办法就是将多态 bean 的作用域由“singleton”变更为“prototype”。
六、Spring 容器中的 Bean 生命周期
1. 实例化一个 Bean,也就是我们通常说的 new
2. 按照 Spring 上下文对实例化的 Bean 进行配置,也就是 IOC 注入
3. 如果这个 Bean 实现了 BeanNameAware 接口,会调用它实现的 setBeanName(String beanId)方法,此处传递的是 Spring 配置文件中 Bean 的 ID
4. 如果这个 Bean 实现了 BeanFactoryAware 接口,会调用它实现的 setBeanFactory(),传递的是 Spring 工厂本身(可以用这个方法获取到其他 Bean)
5. 如果这个 Bean 实现了 ApplicationContextAware 接口,会调用 setApplicationContext(ApplicationContext)方法,传入 Spring 上下文,该方式同样可以实现步骤 4,但比 4 更好,以为 ApplicationContext 是 BeanFactory 的子接口,有更多的实现方法
6. 如果这个 Bean 关联了 BeanPostProcessor 接口,将会调用 postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor 经常被用作是 Bean 内容的更改,并且由于这个是在 Bean 初始化结束时调用 After 方法,也可用于内存或缓存技术
7. 如果这个 Bean 在 Spring 配置文件中配置了 init-method 属性会自动调用其配置的初始化方法
8. 如果这个 Bean 关联了 BeanPostProcessor 接口,将会调用 postAfterInitialization(Object obj, String s)方法
注意:以上工作完成以后就可以用这个 Bean 了,那这个 Bean 是一个 single 的,所以一般情况下我们调用同一个 ID 的 Bean 会是在内容地址相同的实例
9. 当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 接口,会调用其实现的 destroy 方法
10. 最后,如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的销毁方法
评论