Spring常见面试题
Spring框架是一个为Java应用程序的开发提供了综合、广泛的基础性支持的Java平台。使得我们不必担心Spring是如何在后台进行工作的。Spring 是一个“引擎”;
模块有:核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。
使用Spring框架能带来哪些好处?
-
Dependency Injection(DI) 方法使得构造器和JavaBean properties文件中的依赖关系一目了然。
-
与EJB容器相比较,IoC容器更加趋向于轻量级。这样一来IoC容器在有限的内存和CPU资源的情况下进行应用程序的开发和发布就变得十分有利。
-
Spring并没有闭门造车,Spring利用了已有的技术比如ORM框架、logging框架、J2EE、Quartz和JDK Timer,以及其他视图技术。
-
Spring框架是按照模块的形式来组织的。由包和类的编号就可以看出其所属的模块,开发者仅仅需要选用他们需要的模块即可。
-
要测试一项用Spring开发的应用程序十分简单,因为测试相关的环境代码都已经囊括在框架中了。更加简单的是,利用JavaBean形式的POJO类,可以很方便的利用依赖注入来写入测试数据。
-
Spring的Web框架亦是一个精心设计的Web MVC框架,为开发者们在web框架的选择上提供了一个除了主流框架比如Struts、过度设计的、不流行web框架的以外的有力选项。
-
Spring提供了一个便捷的事务管理接口,适用于小型的本地事物处理(比如在单DB的环境下)和复杂的共同事物处理(比如利用JTA的复杂DB环境)。
什么是控制反转(IOC)?什么是依赖注入?
控制反转是一种以给予应用程序中目标组件更多控制为目的设计范式,在运行时被装配器对象来绑定耦合对象的一种编程技巧,使用控制反转的情况下,业务逻辑的流程是由对象关系图来决定的,该对象关系图由装配器负责实例化
依赖注入是控制反转的基础。是在编译阶段尚未知所需的功能是来自哪个的类的情况下,将其他对象所依赖的功能对象实例化的模式。在Java中依赖注入有以下三种实现方式:
-
构造器注入
-
Setter方法注入
-
接口注入
请解释下Spring框架中的IoC?
Spring中的 org.springframework.beans 包和 org.springframework.context``包构成了``Spring``框架``IoC``容器的基础。BeanFactory 接口提供了一个先进的配置机制,使得任何类型的对象的配置成为可能。
BeanFactory 接口提供了一个先进的配置机制,使得任何类型的对象的配置成为可能。ApplicationContex``接口对``BeanFactory(是一个子接口)进行了扩展,在BeanFactory的基础上添加了其他功能,比如与Spring的AOP更容易集成,也提供了处理message resource的机制(用于国际化)、事件传播以及应用层的特别配置,比如针对Web应用的WebApplicationContext。
**org.springframework.beans.factory.BeanFactory** 是Spring IoC容器的具体实现,用来包装和管理前面提到的各种bean。BeanFactory接口是Spring IoC 容器的核心接口。
BeanFactory和ApplicationContext有什么区别?
BeanFactory 可以理解为含有bean集合的工厂类。BeanFactory 包含了种bean的定义,以便在接收到客户端请求时将对应的bean实例化。
BeanFactory还能在实例化对象的时生成协作类之间的关系。此举将bean自身与bean客户端的配置中解放出来。BeanFactory还包含了bean生命周期的控制,调用客户端的初始化方法(initialization methods)和销毁方法(destruction methods)。
从表面上看,application context如同bean factory一样具有bean定义、bean关联关系的设置,根据请求分发bean的功能。但application context在此基础上还提供了其他的功能。
-
提供了支持国际化的文本消息
-
统一的资源文件读取方式
-
已在监听器中注册的bean的事件
以下是三种较常见的 ApplicationContext 实现方式:
1、ClassPathXmlApplicationContext:从classpath的XML配置文件中读取上下文,并生成上下文定义。应用程序上下文从程序环境变量中取得。
ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml”);
2、FileSystemXmlApplicationContext :由文件系统中的XML配置文件读取上下文。
ApplicationContext context = new FileSystemXmlApplicationContext(“bean.xml”);
3、XmlWebApplicationContext:由Web应用的XML文件读取上下文。
Spring有几种配置方式?
https://www.cnblogs.com/sxkgeek/p/9031510.html#_label0详解
-
基于XML的配置
-
基于注解的配置
-
基于Java的配置
请解释Spring Bean的生命周期?
在一个bean实例被初始化时,需要执行一系列的初始化操作以达到可用的状态。同样的,当一个bean不在被调用时需要进行相关的析构操作,并从bean容器中移除。
Spring bean factory 负责管理在spring容器中被创建的bean的生命周期。Bean的生命周期由两组回调(call back)方法组成。
-
初始化之后调用的回调方法。
-
销毁之前调用的回调方法。
Spring框架提供了以下四种方式来管理bean的生命周期事件:
-
InitializingBean和DisposableBean回调接口
-
针对特殊行为的其他Aware接口
-
Bean配置文件中的Custom init()方法和destroy()方法
-
@PostConstruct和@PreDestroy注解方式
使用customInit()和 customDestroy()``方法管理``bean``生命周期的代码样例如下:
<beans>
<bean id="demoBean" class="com.howtodoinjava.task.DemoBean"
init-method="customInit" destroy-method="customDestroy"></bean>
</beans>
Spring Bean的作用域之间有什么区别?
-
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 inner beans?
在Spring框架中,无论何时bean被使用时,当仅被调用了一个属性。一个明智的做法是将这个bean声明为内部bean。内部bean可以用setter注入“属性”和构造方法注入“构造参数”的方式来实现。
比如,在我们的应用程序中,一个Customer类引用了一个Person类,我们的要做的是创建一个Person的实例,然后在Customer内部使用。
public class Customer
{
private Person person;
//Setters and Getters
}
public class Person
{
private String name;
private String address;
private int age;
//Setters and Getters
}
内部bean的声明方式如下:
<bean id="CustomerBean" class="com.howtodoinjava.common.Customer">
<property name="person">
<!-- This is inner bean -->
<bean class="com.howtodoinjava.common.Person">
<property name="name" value="lokesh" />
<property name="address" value="India" />
<property name="age" value="34" />
</bean>
</property>
</bean>
Spring框架中的单例Beans是线程安全的么?
Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的Spring bean并没有可变的状态(比如Serview类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。如果你的bean有多种状态的话(比如 View Model 对象),就需要自行保证线程安全。
最浅显的解决办法就是将多态bean的作用域由“singleton”变更为“prototype”。
请举例说明如何在Spring中注入一个Java Collection?
Spring提供了以下四种集合类的配置元素:
-
: 该标签用来装配可重复的list值。
-
: 该标签用来装配没有重复的set值。
-
: 该标签可用来注入键和值可以为任何类型的键值对。
-
: 该标签支持注入键和值都是字符串类型的键值对。
下面看一下具体的例子:
<beans>
<!-- Definition for javaCollection -->
<bean id="javaCollection" class="com.howtodoinjava.JavaCollection">
<!-- java.util.List -->
<property name="customList">
<list>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>UK</value>
</list>
</property>
<!-- java.util.Set -->
<property name="customSet">
<set>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>UK</value>
</set>
</property>
<!-- java.util.Map -->
<property name="customMap">
<map>
<entry key="1" value="INDIA"/>
<entry key="2" value="Pakistan"/>
<entry key="3" value="USA"/>
<entry key="4" value="UK"/>
</map>
</property>
<!-- java.util.Properties -->
<property name="customProperies">
<props>
<prop key="admin">admin@nospam.com</prop>
<prop key="support">support@nospam.com</prop>
</props>
</property>
</bean>
</beans>
请解释Spring Bean的自动装配?
在Spring框架中共有5种自动装配,让我们逐一分析。
-
no:这是Spring框架的默认设置,在该设置下自动装配是关闭的,开发者需要自行在bean定义中用标签明确的设置依赖关系。
-
byName:该选项可以根据bean名称设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹配 的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
-
byType:该选项可以根据bean类型设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的类型自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
-
constructor:造器的自动装配和byType模式类似,但是仅仅适用于与有构造器相同参数的bean,如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
-
autodetect**:**该模式自动探测使用构造器自动装配或者byType自动装配。首先,首先会尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在bean内部没有找到相应的构造器或者是无参构造器,容器就会自动选择byTpe的自动装配方式。
如何开启基于注解的自动装配?
要使用 @Autowired``,需要注册 AutowiredAnnotationBeanPostProcessor``,可以有以下两种方式来实现:
1、引入配置文件中的<bean>下引入 ``
<beans>
<context:annotation-config />
</beans>
2、在bean配置文件中直接引入AutowiredAnnotationBeanPostProcessor
<beans>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
</beans>
Spring 框架中都用到了哪些设计模式?
-
代理模式—在AOP和remoting中被用的比较多。
-
单例模式—在spring配置文件中定义的bean默认为单例模式。
-
模板方法—用来解决代码重复的问题。比如. RestTemplate,
JmsTemplate,JpaTemplate。 -
前端控制器—Srping提供了
DispatcherServlet``来对请求进行分发。 -
视图帮助(View Helper )—Spring提供了一系列的JSP标签,高效宏来辅助将分散的代码整合在视图里。
-
依赖注入—贯穿于
BeanFactory/ApplicationContext``接口的核心理念。 -
工厂模式—BeanFactory用来创建对象的实例。
FileSystemResource和ClassPathResource有何区别?
ClassPathResource在环境变量中读取配置文件,FileSystemResource在配置文件中读取配置文件。
Spring框架中有哪些不同类型的事件?
Spring的ApplicationContext 提供了支持事件和代码中监听器的功能。
我们可以创建bean用来监听在ApplicationContext 中发布的事件。ApplicationEvent类和在ApplicationContext``接口中处理的事件,如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent 被发布以后,bean会自动被通知。
public class AllApplicationEventListener implements ApplicationListener < ApplicationEvent >
{
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent)
{
//process event
}
}
Spring 提供了以下5中标准的事件:
-
上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
-
上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
-
上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
-
上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
-
请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。
除了上面介绍的事件以外,还可以通过扩展ApplicationEvent 类来开发自定义的事件。
public class CustomApplicationEvent extends ApplicationEvent
{
public CustomApplicationEvent ( Object source, final String msg )
{
super(source);
System.out.println("Created a Custom event");
}
}
为了监听这个事件,还需要创建一个监听器:
public class CustomEventListener implements ApplicationListener < CustomApplicationEvent >
{
@Override
public void onApplicationEvent(CustomApplicationEvent applicationEvent) {
//handle event
}
}
之后通过applicationContext接口的publishEvent()方法来发布自定义事件。
CustomApplicationEvent customEvent = new CustomApplicationEvent(applicationContext, "Test message");
applicationContext.publishEvent(customEvent);
构造方法注入和设值注入有什么区别?
请注意以下明显的区别:
-
在设值注入方法支持大部分的依赖注入,如果我们仅需要注入int、string和long型的变量,我们不要用设值的方法注入。对于基本类型,如果我们没有注入的话,可以为基本类型设置默认值。在构造方法注入不支持大部分的依赖注入,因为在调用构造方法中必须传入正确的构造参数,否则的话为报错。
-
设值注入不会重写构造方法的值。如果我们对同一个变量同时使用了构造方法注入又使用了设置方法注入的话,那么构造方法将不能覆盖由设值方法注入的值。很明显,因为构造方法尽在对象被创建时调用。
-
在使用设值注入时有可能还不能保证某种依赖是否已经被注入,也就是说这时对象的依赖关系有可能是不完整的。而在另一种情况下,构造器注入则不允许生成依赖关系不完整的对象。
-
在设值注入时如果对象A和对象B互相依赖,在创建对象A时Spring会抛出s
ObjectCurrentlyInCreationException异常,因为在B对象被创建之前A对象是不能被创建的,反之亦然。所以Spring用设值注入的方法解决了循环依赖的问题,因对象的设值方法是在对象被创建之前被调用的。
请举例说明@Qualifier注解?
@Qualifier``注解意味着可以在被标注``bean``的字段上可以自动装配。Qualifier注解可以用来取消Spring不能取消的bean应用。
下面的示例将会在Customer的person属性中自动装配person的值。
public class Customer
{
@Autowired
private Person person;
}
下面我们要在配置文件中来配置Person类。
<bean id="customer" class="com.howtodoinjava.common.Customer" />
<bean id="personA" class="com.howtodoinjava.common.Person" >
<property name="name" value="lokesh" />
</bean>
<bean id="personB" class="com.howtodoinjava.common.Person" >
<property name="name" value="alex" />
</bean>
Spring``会知道要自动装配哪个person bean么?不会的,但是运行上面的示例时,``会抛出下面的异常:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [com.howtodoinjava.common.Person] is defined:
expected single matching bean but found 2: [personA, personB]
要解决上面的问题,需要使用 @Quanlifier注解来告诉Spring容器要装配哪个bean:
public class Customer
{
@Autowired
@Qualifier("personA")
private Person person;
}
摘自CTOlib码库

浙公网安备 33010602011771号