0. 讲一下什么是Spring

Spring是一个轻量级的IoC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于XML的配置、基于注解的配置、基于Java的配置。
主要由以下几个模块组成:
Spring Core:核心类库,提供IOC服务;
Spring Context:提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等);
Spring AOP:AOP服务;
Spring DAO:对JDBC的抽象,简化了数据访问异常的处理
Spring ORM:对现有的ORM框架的支持;
Spring Web:提供了基本的面向Web的综合特性,例如多方文件上传;
Spring MVC:提供面向Web应用的Model-View-Controller实现。

1. IOC

(1)如何实现一个IOC容器

Spring面试_AOP

(2)IOC理解

Spring面试_面试_02

(3)BeanFactory

BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合我们都直接使用 ApplicationContext 而非底层的BeanFactory。

Spring面试_面试_03

Spring面试_spring_04

(4)ApplicationContext

ApplicationContext 由 BeanFactory 派 生 而 来 , 提 供 了 更 多 面 向 实 际 应 用 的 功 能 。

Spring面试_AOP_05

(5)BeanFactory 和 ApplicationContext有什么区别?

BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做 Spring的容器。

1)包目录不同
spring-beans.jar 中 org.springframework.beans.factory.BeanFactory
spring-context.jar 中 org.springframework.context.ApplicationContext

2)def:

BeanFactory: 简单粗暴,可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例。通常只提供注册(put),获取(get)这两个功能。我们可以称之为 低级容器

ApplicationContext: 可以称之为高级容器。因为他比 BeanFactory 多了更多的功能。他继承了多个接口。因此具备了更多的功能。所以你看他的名字,已经不是 BeanFactory 之类的工厂了,而
是 “应用上下文”, 代表着整个大容器的所有功能。该接口定义了一个 refresh 方法,此方法是所有阅读Spring 源码的人的最熟悉的方法,用于刷新整个容器,即重新加载/刷新所有的 bean。

3)实现原理:

BeanFactory:BeanFactory是Spring的心脏,低级容器

3.1)加载配置文件,解析成 BeanDefinition 放在 Map 里。
3.2)调用 getBean 的时候,从 BeanDefinition 所属的 Map 里,拿出Class 对象进行实例化,同时,如果有依赖关系,将递归调用 getBean 方法完成依赖注入

3.3)getBean方法是IOC容器获取bean对象和引发依赖注入的起点。方法的功能是返回特定的名称的Bean

ApplicationContext:ApplicationContext就是完整的躯体,高级容器
包含了低级容器的功能,当他执行 refresh 模板方法的时候,将刷新整个容器的 Bean。作为高级容器,功能更全。BeanFactorty接口提供了配置框架及基本功能,但是无法支持spring的aop功能和web应用。一句话,他不仅仅是 IoC。他支持不同信息源头,支持BeanFactory 工具类,支持层级容器,支持访问文件资源,支持事件发布通知,支持接口回调等等。
4)依赖关系:
BeanFactory:是Spring里面最底层的接口,包含了各种Bean的定义,读取 bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean 之间的依赖关系。
ApplicationContext接口:是BeanFactory的子接口,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能。

5)加载方式
BeanFactroy:采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean 时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。
ApplicationContext:它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

6)创建方式
BeanFactory:通常以编程方式被创建。

ApplicationContext:能以编程方式和声明方式创建,如使用ContextLoader。

7)注册方式

BeanFactory和ApplicationContext都支持BeanPostProcessor,BeanFactoryPostProcessor的使用

BeanFactory:手动注册
ApplicationContext:自动注册

8)底层资源的访问

ApplicationContext 扩展了 ResourceLoader(资源加载器)接口,从而可以用来加载多个
Resource,而 BeanFactory 是没有扩展 ResourceLoader。

9)强大的事件机制(Event)

基本上牵涉到事件(Event)方面的设计,就离不开观察者模式,ApplicationContext 的事件机制
主要通过 ApplicationEvent 和 ApplicationListener 这两个接口来提供的,和 Java swing 中的事件
机制一样。即当 ApplicationContext 中发布一个事件时,所有扩展了 ApplicationListener 的 Bean
都将接受到这个事件,并进行相应的处理。

10)BeanFactory和ApplicationContext的关系

Spring面试_动态代理_06

(6)BeanFactory和FactoryBean

BeanFactory:Bean工厂,是一个工厂(Factory),我们Spring IoC容器的最顶层接口就是这个
BeanFactory,它的作用是管理Bean,即实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
FactoryBean:工厂Bean,是一个Bean,作用是产生其他bean实例。通常情况下,这种bean没有什么特别的要求,仅需要提供一个工厂方法,该方法用来返回其他bean实例。通常情况下,bean无须自己实现工厂模式,Spring容器担任工厂角色;但少数情况下,容器中的bean本身就是工厂,其作用是产生其它bean实例。
(7)ApplicationContext通常的实现是什么?

FileSystemXmlApplicationContext :此容器从一个XML文件中加载beans 的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。
ClassPathXmlApplicationContext:此容器也从一个XML文件中加载beans 的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找 bean配置。
WebXmlApplicationContext:此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean。

(8)什么是 bean 装配?

装配,或 bean 装配是指在 Spring 容器中把 bean 组装到一起,前提是容器需要知道 bean
的依赖关系,如何通过依赖注入来把它们装配到一起

(9)什么是bean的自动装配

Spring 容器能够自动装配相互合作的 bean,这意味着容器不需要<constructor-arg>和
<property>配置,能通过 Bean 工厂自动处理 bean 之间的协作。

Spring面试_AOP_07

(10)如何创建一个如何给Spring 容器提供配置元数据?Spring有几种配置方式?
1)XML配置文件

bean 所需的依赖项和服务在 XML 格式的配置文件中指定。这些配置文件通常包含许多 bean 定义和特定于应用程序的配置选项。它们通常以 bean 标签开头。

<bean id="studentbean" class="org.edureka.firstSpring.StudentBean">
<property name="name" value="Edureka"></property>
</bean>

2)基于注解的配置

您可以通过在相关的类,方法或字段声明上使用注解,将 bean 配置为组件类本身,而不是使用 XML 来描述 bean 装配。

3)基于java API的配置

Spring 的 Java 配置是通过使用 @Bean 和 @Configuration 来实现。
3.1)  @Bean 注解扮演与 <bean/> 元素相同的角色。
3.2)  @Configuration 类允许通过简单地调用同一个类中的其他 @Bean 方法
来定义 bean 间依赖关系。

@Configuration
public class StudentConfig {
@Bean
public StudentBean myStudent() {
return new StudentBean();
}
}

(11)5 种不同方式的自动装配

Spring面试_spring_08

(12)自动装配有哪些局限性?

重写:您始终可以使用 <constructor-arg> 和 <property> 设置指定依赖项,这将覆盖自动装配。
基本数据类型:简单属性(如原数据类型,字符串和类)无法自动装配。
模糊特性:自动装配不如显式装配精确,如果有可能,建议使用显式装配。

(13)怎样开启注解装配?

注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在 Spring 配置文件中配置 context:annotation-config/元素。

(14)使用@Autowired注解自动装配的过程是怎样的?
使用@Autowired注解来自动装配指定的bean。在使用@Autowired注解之前需要在Spring配置文件进行配置。
在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的 bean,并装配给该对象的属性。在使用@Autowired时,首先在容器中查询对应类型的bean:
如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;
如果查询的结果不止一个,那么@Autowired会根据名称来查找;
如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false。

(15)在 Spring 中如何注入一个 java 集合?

Spring 提供以下几种集合的配置元素:

<list>类型用于注入一列值,允许有相同的值。
<set>类型用于注入一组值,不允许有相同的值。
<map>类型用于注入一组键值对,键和值都可以为任意类型。
<props>类型用于注入一组键值对,键和值都只能为 String 类型。

(16)什么是Spring的依赖注入?

控制反转IoC是一个很大的概念,可以用不同的方式来实现。其主要实现方式有两种:依赖注入和依赖查找依赖注入:相对于IoC而言,依赖注入(DI)更加准确地描述了IoC的设计理念。所谓依赖注入(Dependency Injection),即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。
(17)依赖注入的基本原则

依赖注入的基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。容器全权负责组件的装配,它会把符合依赖关系的对象通过属性(JavaBean中的setter)或者是构造器传递给需要的对象。
(18)依赖注入有什么优势

查找定位操作与应用代码完全无关。
不依赖于容器的API,可以很容易地在任何容器以外使用应用对象。
不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器。

(19)Spring 依赖注入几种方式

0)接口注入(Interface Injection):作废

1)构造器注入(Constructor Injection):构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。

2)setter方法注入(Setter Injection):Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。

Spring面试_java_09

(20)Spring框架中的单例bean是线程安全的吗?

不是,Spring框架中的单例bean不是线程安全的
spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。
实际上大部分时候 spring bean 无状态的(比如 dao 类),所有某种程度上来说 bean 也是安全的,但如果 bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了,最简单的就是改变 bean 的作用域,把“singleton”变更为“prototype”,这样请求 bean 相当于 new Bean() 了,所以就可以保证线程安全了。
有状态就是有数据存储功能。
无状态就是不会保存数据。

(21)Spring如何处理线程并发问题?
在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。
ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。
ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

(22)哪些是重要的bean生命周期方法? 你能重载它们吗?

有两个重要的bean 生命周期方法,第一个是setup , 它是在容器加载bean的时候被调用。第二个方法是 teardown 它是在容器卸载类的时候被调用。bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。

(23)什么是Spring的内部bean?什么是Spring inner beans?

在Spring框架中,当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean。内部bean可以用setter注入“属性”和构造方法注入“构造参数”的方式来实现,内部bean通常是匿名的,它们的Scope一般是prototype。

2. AOP

(1)AOP理解

Spring面试_动态代理_10

Spring面试_spring_11

(2)AOP 核心概念

1)切面(aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象
2)横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。
3)连接点(joinpoint):被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在 Spring 中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
4)切入点(pointcut):对连接点进行拦截的定义
5)通知(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类。
6)目标对象:代理的目标对象
7)织入(weave):将切面应用到目标对象并导致代理对象创建的过程 8、引(introduction):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段。

(3)AOP 主要应用场景

Spring面试_java_12

(4)如何理解 Spring 中的代理?

将 Advice 应用于目标对象后创建的对象称为代理。在客户端对象的情况下,目标对象和代理对象是相同的。

代理对象的方法 = 增强处理 + 被代理对象的方法

Advice + Target Object = Proxy

 (5)Spring AOP and AspectJ AOP 有什么区别?AOP 有哪些实现方式?

Spring AOP是属于运行时增强,而AspectJ是编译时增强。

Spring AOP基于代理(Proxying),而AspectJ基于字节码操作(Bytecode Manipulation)。
Spring AOP已经集成了AspectJ,AspectJ应该算得上是Java生态系统中最完整的AOP框架了。
AspectJ相比于Spring AOP功能更加强大,但是Spring AOP相对来说更简单。
如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择AspectJ,它比SpringAOP快很多。

AOP实现的关键在于代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ 的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。

1) AspectJ静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。

2) Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法

(6)AOP 两种动态代理方式

Spring 提供了两种方式来生成代理对象: JDKProxy 和 Cglib,具体使用哪种方式生成由
AopProxyFactory 根据 AdvisedSupport 对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK 动态代理技术,否则使用 Cglib 来生成代理。
1)JDK 动态代理
JDK 动态代理主要涉及到 java.lang.reflect 包中:InvocationHandler接口和Proxy类
InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织
在一起
;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的
代理对象。
2)CGLib 动态代理
如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标
类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定
类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP
。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的

@Aspect public class TransactionDemo {
@Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))")
public void point(){
}
@Before(value="point()")
public void before(){
System.out.println("transaction begin");
}
@AfterReturning(value = "point()")
public void after(){
System.out.println("transaction commit");
}
@Around("point()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("transaction begin"); joinPoint.proceed();
System.out.println("transaction commit");
}
}

3)区别

Spring面试_AOP_13

Spring面试_面试_14

在功能上讲,实际上Cglib代理并不如JDK代理(如果大家都按接口-实现的方式来设计类)。但是从效率上将,Cglib远胜JDK代理。其实从原理也能理解,直接通过类的方法调用,肯定要比通过反射调用的时间更短。

(7)纵观 AOP 编程,其中需要程序员参与的只有 3 个部分:
1)定义普通业务组件。
2)定义切入点,一个切入点可能横切多个业务组件。
3)定义增强处理,增强处理就是在 AOP 框架为普通业务组件织入的处理动作。

(8)连接点的支持,而且它不支持构造器连接点。方法之外的连接点拦截功能,我们在Spring AOP 中,关注点和横切关注的区别是什么?在spring aop 中 concern 和 cross-cutting concern 的不同之处

关注点(concern)是应用中一个模块的行为,一个关注点可能会被定义成一个我们想实现的一个功能。
横切关注点(cross-cutting concern)是一个关注点,此关注点是整个应用都会使用的功能,并影响整个应用,比如日志,安全和数据传输,几乎应用的每个模块都需要的功能。因此这些都属于横切关注点。

连接点:代表一个应用程序的某个位置,在这个位置我们可以插入一个AOP切面,它实际上是个应用程序执行Spring AOP的位置。

切入点:一个或一组连接点,通知将在这些位置执行。可以通过表达式或匹配的方式指明切入点。

(9)什么是切面 Aspect?

aspect 由 切点pointcount 和 通知advice 组成。 它既包含了横切逻辑的定义, 也包括了连接点的定义. Spring AOP 就是负责实施切面的框架, 它将切面所定义的横切逻辑编织到切面所指定的连接点中。
AOP 的工作重心在于如何将增强编织目标对象的连接点上, 这里包含两个工作:
1)如何通过 pointcut 和 advice 定位到特定的 joinpoint 上。
2)如何在 advice 中编写切面代码。
可以简单地认为, 使用 @Aspect 注解的类就是切面

Spring面试_spring_15

(10)有几种不同类型的自动代理?
BeanNameAutoProxyCreator
DefaultAdvisorAutoProxyCreator
Metadata autoproxying

(11)什么是织入。什么是织入应用的不同点?
织入是将切面和到其他应用类型或对象连接或创建一个被通知对象的过程
织入可以在编译时,加载时,或运行时完成。
 

3. Spring框架中都用到了哪些设计模式?

简单工厂模式:Spring 中的 BeanFactory 就是简单工厂模式的体现。根据传入一个唯一的标识来获得 Bean 对象,但是在传入参数后创建还是传入参数前创建,要根据具体情况来定。
工厂模式:Spring 中的 FactoryBean 就是典型的工厂方法模式,实现了 FactoryBean 接口的 bean
是一类叫做 factory 的 bean。其特点是,spring 在使用 getBean() 调用获得该 bean 时,会自动调
用该 bean 的 getObject() 方法,所以返回的不是 factory 这个 bean,而是这个 bean.getOjbect()
方法的返回值。
单例模式:在 spring 中用到的单例模式有: scope="singleton" ,注册式单例模式,bean 存放于
Map 中。bean name 当做 key,bean 当做 value。
原型模式:在 spring 中用到的原型模式有: scope="prototype" ,每次获取的是通过克隆生成的新
实例,对其进行修改时对原有实例对象不造成任何影响。
迭代器模式:在 Spring 中有个 CompositeIterator 实现了 Iterator,Iterable 接口和 Iterator 接
口,这两个都是迭代相关的接口。可以这么认为,实现了 Iterable 接口,则表示某个对象是可被迭
代的。Iterator 接口相当于是一个迭代器,实现了 Iterator 接口,等于具体定义了这个可被迭代的
对象时如何进行迭代的。
代理模式:Spring 中经典的 AOP,就是使用动态代理实现的,分 JDK 和 CGlib 动态代理。
适配器模式:Spring 中的 AOP 中 AdvisorAdapter 类,它有三个实现:
MethodBeforAdviceAdapter、AfterReturnningAdviceAdapter、ThrowsAdviceAdapter。Spring
会根据不同的 AOP 配置来使用对应的 Advice,与策略模式不同的是,一个方法可以同时拥有多个
Advice。Spring 存在很多以 Adapter 结尾的,大多数都是适配器模式。
观察者模式:Spring 中的 Event 和 Listener。spring 事件:ApplicationEvent,该抽象类继承了
EventObject 类,JDK 建议所有的事件都应该继承自 EventObject。spring 事件监听器:
ApplicationListener,该接口继承了 EventListener 接口,JDK 建议所有的事件监听器都应该继承
EventListener。
模板模式:Spring 中的 org.springframework.jdbc.core.JdbcTemplate 就是非常经典的模板模式
的应用,里面的 execute 方法,把整个算法步骤都定义好了。

责任链模式:DispatcherServlet 中的 doDispatch() 方法中获取与请求匹配的处理器
HandlerExecutionChain,this.getHandler() 方法的处理使用到了责任链模式。
 

4. Spring 是怎么解决循环依赖的?

Spring面试_spring_16

整个流程大致如下:
1)首先 A 完成初始化第一步并将自己提前曝光出来(通过 ObjectFactory 将自己提前曝光),在
初始化的时候,发现自己依赖对象 B,此时就会去尝试 get(B),这个时候发现 B 还没有被创建出来;
2)然后 B 就走创建流程,在 B 初始化的时候,同样发现自己依赖 C,C 也没有被创建出来;
3)这个时候 C 又开始初始化进程,但是在初始化的过程中发现自己依赖 A,于是尝试 get(A)。这
个时候由于 A 已经添加至缓存中(一般都是添加至三级缓存 singletonFactories),通过
ObjectFactory 提前曝光,所以可以通过 ObjectFactory的getObject() 方法来拿到 A 对象。C 拿
到 A 对象后顺利完成初始化,然后将自己添加到一级缓存中;
4)回到 B,B 也可以拿到 C 对象,完成初始化,A 可以顺利拿到 B 完成初始化。到这里整个链路
就已经完成了初始化过程了。
关键字:三级缓存,提前曝光。

5. Spring数据访问

(1)spring DAO 有什么用?
Spring DAO 使得 JDBC,ORM框架等数据访问技术更容易以一种统一的方式工作。这使得用户容易在持久性技术之间切换。它还允许您在编写代码时,无需考虑捕获每种技术不同的异常。

(2)列举 Spring DAO 抛出的异常

Spring面试_java_17

(3)解释对象/关系映射集成模块

Spring 通过提供 ORM 模块,支持我们在直接 JDBC 之上使用一个对象/关系映射映射(ORM)工具,Spring 支持集成主流的 ORM 框架,如 Hiberate,JDO 和 iBATIS SQL Maps。Spring 的事务管理同样支持以上所有 ORM 框架及 JDBC。

(4)Spring 支持的 ORM
Spring 支持以下 ORM:
 Hibernate
 iBatis
 JPA(JavaPersistenceAPI)
 TopLink
 JDO(JavaDataObjects)
 OJB
 

6. Spring 框架中有哪些不同类型的事件?

1)上下文更新事件(ContextRefreshedEvent):该事件会在 ApplicationContext 被初始化或者更
新时发布。也可以在调用 ConfigurableApplicationContext 接口中的 refresh()方法时被触发。
2)上下文开始事件(ContextStartedEvent):当容器调用 ConfigurableApplicationContext 的
Start()方法开始/重新开始容器时触发该事件。
3)上下文停止事件(ContextStoppedEvent):当容器调用 ConfigurableApplicationContext 的
Stop()方法停止容器时触发该事件。
4)上下文关闭事件(ContextClosedEvent):当 ApplicationContext 被关闭时触发该事件。容器被关闭时,其管理的所有单例 Bean 都被销毁。

5)请求处理事件(RequestHandledEvent):在 Web 应用中,当一个 http 请求(request)结束触发该事件。

7. FileSystemResource 和 ClassPathResource 有何区别?

简而言之, ClassPathResource 在环境变量中读取配置文件, FileSystemResource 在配置文件中读取配置文件。

8. 为什么说 Spring 是一个容器?

因为用来形容它用来存储单例的 bean 对象这个特性。