Spring面试题
什么是 Spring 框架?Spring 框架有哪些主要模块?
Spring是一个轻量级的JavaEE解决方案,整合众多优秀的设计模式。
spring框架主要包括7个模块:
- Spring AOP 面向切面编程
- Spring ORM Hibernate|mybatis|JDO
- Spring Core 提供bean工厂 IOC
- Spring Dao JDBC支持
- Spring Context 提供了关于UI支持,邮件支持等
- Spring Web 提供了web的一些工具类的支持
- Spring MVC 提供了web mvc , webviews , jsp ,pdf ,export
使用 Spring 框架能带来哪些好处?
- 轻量:Spring 是轻量的,基本的版本大约 2MB
- 控制反转:Spring 通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们
- 面向切面的编程(AOP):Spring 支持面向切面的编程,并且把应用业务逻辑和系统服务分开
- 容器:Spring 包含并管理应用中对象的生命周期和配置
- MVC 框架:Spring 的 WEB 框架是个精心设计的框架,是 Web 框架的一个很好的替代品
- 事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)
- 异 常 处 理 : Spring 提 供 方 便 的 API 把 具 体 技 术 相 关 的 异 常 ( 比 如 由 JDBC ,Hibernate or JDO 抛出的)转化为一致的 unchecked 异常
什么是控制反转(IOC)?什么是依赖注入?
将创建对象的权利由手动创建转换为Spring自动创建。将对象之间的依赖关系通过配置的方式注入到另一个对象中的过程。
请解释下 Spring 框架中的 IoC?
IOC 意为控制反转,普通javaEE创建对象是通过在程序中通过new创建,但是在Spring中,只需将设计好的类通过配置文件或注解的方式设定好,即可由Spring自动创建,对象的控制权由程序转移到了Spring,Spring通过工厂+反射生成对象,将对象放置在IOC容器中。
BeanFactory 和 ApplicationContext 有什么区别?
BeanFactory是Spring的顶级接口,只提供了最基础的容器功能。通过BeanFactory装载Bean是延时创建。
ApplicationContext是BeanFactory的高级实现,其中增加了许多资源加载,国际化,AOP,消息发送响应机制。通过ApplicationContext装载Bean是在Spring启动时立即创建。
Spring 有几种配置方式?
三种方式:xml,注解,java方式(配置类 @Bean)
如何用基于 XML 配置的方式配置 Spring?
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService" class="sun.service.ServiceImpl.UserServiceImpl"></bean> </beans>
如何用基于 Java 配置的方式配置 Spring?
@Configuration public class AppConfig{ @Bean public MyService myService() { return new MyServiceImpl(); } }
怎样用注解的方式配置 Spring?
1、在Spring配置文件中开启注解配置。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
</beans>2、通过@Autowired @Component 等注解进行Bean加载和注入
请解释 Spring Bean 的生命周期?
- 首先是实例化、属性赋值、初始化、销毁这 4 个大阶段;
- 再是初始化的具体操作,有 Aware 接口的依赖注入、BeanPostProcessor 在初始化前后的处理以及 InitializingBean 和 init-method 的初始化操作;
- 销毁的具体操作,有注册相关销毁回调接口,最后通过DisposableBean 和 destory-method 进行销毁。
Spring Bean 的作用域之间有什么区别?
Spring的 bean有5种作用域分别是:singleton、prototype、request、session和globalSession
singleton
全局只有一个实例
prototype
每次调用产生一个新的实例
在web使用的时候还有三个作用域,但是必须在web.xml中注册一个RequestContextListener , 目的是为了设置每次请求开始和结束都可以使spring得到相应的事件。
request
每次请求产生一个bean
session
每个用户session可以产生一个新的bean,不同用户之间的bean互相不影响
globalSession
作用和session类似,只是使用portlet的时候使用。
什么是 Spring inner beans?
在Spring 框架中,无论何时bean 被使用时,当仅被调用了一个属性。一个明智的做法是将这个bean声明为内部bean。内部bean 可以用setter 注入“属性”和构造方法注入“构造参数”的方式来实现。比如,在我们的应用程序中,一个Customer 类引用了一个Person 类,我们的要做的是创建一个Person的实例,然后在Customer 内部使用。
public class Customer{ private Person person; } public class Person{ private String name; private String address; private int age; }<bean id="CustomerBean" class="com.leon.common.Customer"> <property name="person"> <bean class="com.leon.common.Person"> <property name="name" value="lokesh" /> <property name="address" value="India" /> <property name="age" value="34" /> </bean> </property> </bean>
Spring 框架中的单例 Beans 是线程安全的么?
prototype:每次请求都会创建新的Bean,线程之间不存在Bean的共享,因此是线程安全的。
singleton: 由于全局只有一个Bean,因此可能会出现线程安全问题。但是由于单例Bean,大都是无状态的Bean,也就是不会对Bean成员执行查询以外的操作,因此不会出现线程安全问题。
请举例说明如何在 Spring 中注入一个 Java Collection?
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService3" class="sun.service.ServiceImpl.UserServiceImpl3"> <property name="strings"> <array> <value>kelvin</value> <value>jack</value> <value>tony</value> </array> </property> <property name="set"> <set> <value>kelvin</value> <value>jack</value> <value>tony</value> </set> </property> <property name="list"> <list> <value>kelvin</value> <value>jack</value> <value>tony</value> </list> </property> <property name="map"> <map> <entry key="kelvin" value="23"></entry> <entry key="jack" value="21"></entry> <entry key="tony"> <value>46</value> </entry> </map> </property> </bean> </beans>
如何向 Spring Bean 中注入一个 Java.util.Properties?
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService3" class="sun.service.ServiceImpl.UserServiceImpl3"> <property name="prop"> <props> <prop key="kelvin">23</prop> <prop key="jack">45</prop> <prop key="tony">32</prop> </props> </property>
</bean> </beans>
请解释 Spring Bean 的自动装配?
是什么?
spring中提供了向Bean中自动注入依赖的功能,这个过程就是自动装配,当向bean中注入的内容非常多的时候,自动注入依赖的功能将极大的节省注入程序的时间。
有哪些类型?
基于xml:在<bean>标签内通过autowire=byType byName constructor 决定注入类型判断方式
<bean id="userDao“ class="com.spring.springioc.dao.impl.UserDaoImpl”/> <!--byType根据类型自动装配userDao--> <bean id="userService" autowire="byType" class="com.spring.springioc.service.impl.UserServiceImpl"/><bean id="userDao" class="com.spring.springioc.dao.impl.UserDaoImpl"/> <!--这个bean是userDao类型的,但不是要注入的类型--> <bean id="userDao2" autowire-candidate="false" class="com.spring.springioc.dao.impl.userDaoImpl"/> <bean id="userService" autowire="byType" class="com.spring.springioc.service.impl.userSericeImpl"/>基于注解:@Autowired @Qualifier @Resource @Value
请解释自动装配模式的区别?
- no: 这是Spring框架的默认设置,在该设置下自动装配是关闭的,开发者需要自行在bean定义中用标签明确的设置依赖关系。
- byName: 该选项可以根据bean名称设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
- byType: 该选项可以根据bean类型设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的类型自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
- constructor: 造器的自动装配和byType模式类似,但是仅仅适用于与有构造器相同参数的bean,如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
- autodetect: 该模式自动探测使用构造器自动装配或者byType自动装配。首先,首先会尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在bean内部没有找到相应的构造器或者是无参构造器,容器就会自动选择byTpe的自动装配方式。
如何开启基于注解的自动装配?
- 引入配置文件中的
<bean>
下引入<context:annotation-config>
<beans> <context:annotation-config /> </beans>
- 在bean配置文件中直接引入
AutowiredAnnotationBeanPostProcessor
<beans> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> </beans>
请举例解释@Required 注解?请举例解释@Autowired 注解?请举例说明@Qualifier 注解?
@Required
检查属性是否被正确设置。
RequiredAnnotationBeanPostProcessor 是 Spring 中的后置处理用来验证被 @Required 注解的 bean 属性是否被正确的设置了。在使用 RequiredAnnotationBeanPostProcesso 来验证 bean 属性之前,首先要在 IoC 容器中对 其进行注册:
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotatio nBeanPostProcessor" />但是如果没有属性被用 @Required 注解过的话,后置处理器会抛出一个 BeanInitializationException 异常。
@Autowired
@Autowired 注解对自动装配何时何处被实现提供了更多细粒度的控制。@Autowired 注解可 以像@Required 注解、构造器一样被用于在 bean 的设值方法上自动装配 bean 的属性,一个参数或者带有任意名称或带有多个参数的方法。
比如,可以在设值方法上使用@Autowired 注解来替代配置文件中的 元 素。当 Spring 容器在 setter 方法上找到@Autowired 注解时,会尝试用 byType 自动装配。
当然我们也可以在构造方法上使用@Autowired 注解。带有@Autowired 注解的构造方法意味着 在创建一个 bean 时将会被自动装配,即便在配置文件中使用 元素。@Qualifier
@Qualifier 注解意味着可以在被标注 bean 的字段上可以自动装配。通常和@Autowired配合使用
构造方法注入和设值注入有什么区别?
设值注入的优势:
- 设值注入写法直观便于理解,使各种关系清晰明了。
- 设值注入可以避免因复杂的依赖实例化时所造成的性能问题。
- 设值注入的灵活性较强。
构造方法注入的优势:
- 构造方法注入可以决定依赖关系的注入顺序,有限依赖的优先注入。
- 对于依赖关系无需变化的Bean,构造方法注入使所有的依赖关系全部在构造器内设定,可避免后续代码对依赖关系的破坏。
- 构造方法注入中只有组建的创建者才能改变组建的依赖关系,更符合高内聚原则。
建议:
采用设值注入为主,构造注入为辅的注入策略。依赖关系无需变化时,尽量采用构造注入,而其它的依赖关系的注入,则考虑设值注入。
构造器参数实现强制依赖,setter 方法实现可选依赖。
Spring 框架中有哪些不同类型的事件?
- 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
- 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
- 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
- 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
- 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。
FileSystemResource 和 ClassPathResource 有何区别?
在FileSystemResource 中需要给出spring-config.xml文件在你项目中的相对路径或者绝对路径。在ClassPathResource中spring会在ClassPath中自动搜寻配置文件,所以要把ClassPathResource 文件放在ClassPath下。
如果将spring-config.xml保存在了src文件夹下的话,只需给出配置文件的名称即可,因为src文件夹是默认。
简而言之,ClassPathResource在环境变量中读取配置文件,FileSystemResource在配置文件中读取配置文件。
Spring 框架中都用到了哪些设计模式?
- 代理模式—在AOP和remoting中被用的比较多。
- 单例模式—在spring配置文件中定义的bean默认为单例模式。
- 模板方法—用来解决代码重复的问题。
- 前端控制器—Srping提供了DispatcherServlet来对请求进行分发。
- 视图帮助(View Helper )—Spring提供了一系列的JSP标签,高效宏来辅助将分散的代码整合在视图里。
- 依赖注入—贯穿于BeanFactory / ApplicationContext接口的核心理念。
- 工厂模式—BeanFactory用来创建对象的实例。