我收集了一些spring面试的问题,这些问题可能会在下一次技术面试中遇到。对于其余spring模块,我将单独分享面试问题和答案。前端
若是你能将在之前面试中碰到的,且你认为这些应该是一个有spring经验的人可能被问到的问题发给我,我将不胜感激!java
我将把它们添加到这个列表中。这将对其余学习者也会有很大的帮助。web
1. 什么是Spring框架?它的主要模块有哪些?面试
2. 使用Spring框架的好处是什么?spring
3.什么是控制反转(IoC)和依赖注入?数据库
4. 在Spring框架中的IoC是怎么样子的 ?编程
5. BeanFactory和ApplicationContext之间的区别?json
6. 将Spring配置到应用程序中的方式有哪些?设计模式
7. 基于xml的Spring配置是什么样子的?安全
8. 基于Spring java的配置是什么样子的?
9. 基于Spring注解的配置是什么样子的?
10. 请解释一下Spring Bean的生命周期?
11. Spring Bean做用域的有哪些?
12. Spring的内部Bean是什么?
13. 在Spring框架中,单例bean线程安全吗?
14. 如何在Spring中注入Java集合?请给个例子好吗?
15. 如何将一个java.util.属性注入到Spring Bean?
16. 解释一下Spring Bean的自动注入式什么样的?
17. 请解释一下不一样的bean自动注入模式?
18. 怎么打开基于注释的自动注入的?
19. 可否用例子解释一下@ required注解吗?
20.可否用例子解释一下@ autowired注解吗?
21. 可否用例子讲解一下@qualifier注解吗?
22. 构造方法注入和setter注入之间的区别吗?
23. spring框架的事件类型有哪些?
24. FileSystemResource和ClassPathResource之间的区别吗?
25. 列举一些Spring框架中使用的设计模式?
Spring框架是一个Java平台,提供全面的基础设施支持开发Java应用程序。Spring处理基础设施部分,这样你就能够专一于应用程序部分。Spring框架内,把一级对象经过设计模式封装起来,您能够放心的集成到您本身的应用程序而不用关注他们如何在后台工做。
目前,Spring框架由功能组织成大约20个模块。这些模块分为核心容器、数据访问/集成、Web,AOP(面向切面的编程)、instrument(支持和类加载器的实现来在特定的应用服务器上使用)、消息、和测试,以下列图所示。
下面是一些使用Spring框架的好处的列表:
依赖注入和控制反转是对同一件事情的不一样描述,从某个方面讲,就是它们描述的角度不一样。
依赖注入是从应用程序的角度在描述,能够把依赖注入描述完整点:应用程序依赖容器建立并注入它所须要的外部资源;
而控制反转是从容器的角度在描述,描述完整点:容器控制应用程序,由容器反向的向应用程序注入应用程序所须要的外部资源。
在Java中,依赖注入可能发生三种方法:
org.springframework.beans
和org.springframework.context
包是Spring框架IoC容器的基础。
BeanFactory
接口提供了一个高级的配置机制来管理任意属性的对象。
ApplicationContext
接口基于BeanFactory构建的
(是一个子接口)并添加其余功能,如Spring的AOP功能,信息资源处理(用于国际化)、事件传播和应用程序层的特定上下文如在web应用程序中使用WebApplicationContext
。
org.springframework.beans.factory.BeanFactory是
Spring IoC容器真是展示,负责管理上述bean。BeanFactory接口是Spring IoC容器接口的核心。
一个BeanFactory
就像包含bean集合的工厂类。BeanFactory在内部
持有多个Bean的定义,当客户端请求bean时,将bean进行实例化。
初始化时BeanFactory
可以保持对象的依赖关系。这减轻了负担从bean自己和bean客户机的配置。 BeanFactory在
一个bean的生命周期也能其做用,它能够调用bean的自定义初始化和销毁方法。
表面上看,applicationContext和BeanFactory是同样。一样加载bean定义,将bean链接在一块儿,分发bean。但applicationContext还提供:
三个经常使用的ApplicationContext实现是:
ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml”);
FileSystemXmlApplicationContext
:它从文件系统的一个XML文件加载上下文定义的。从文件系统加载应用程序上下文经过以下代码实现。
ApplicationContext context = new FileSystemXmlApplicationContext(“bean.xml”);
XmlWebApplicationContext
:它从一个web应用程序中包含的XML文件加载context。配置spring到您的应用程序有三种方式:
在Spring框架中,bean所需的依赖和服务在定义在配置文件中,配置文件一般是XML格式。一般这些配置文件都以<beans>
标签开始,含有大量的bean定义和特定于应用程序的配置选项。Spring XML配置的主要目标是让全部spring组件经过使用XML配置文件。
这意味着不会出现任何其余类型的Spring配置(如经过Java类注释或配置)。Spring XML配置中使用Spring命名空间提供的XML标记中使用的配置;Spring命名空间主要有:context、bean、jdbc、tx, aop, mvc等。
<beans> <!-- JSON Support --> <bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/> <bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/> </beans>
最简单的让您的应用程序加载配置文件和配置运行时组件方式是在web.xml
文件中配置DispatcherServlet,以下所示:
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>spring</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
在支持spring的新java配置组件中,@Configuration注解
的类和@Bean注解
的方法是核心组件。
@Bean
注解用于经过方法来实例化,配置和初始化一个新的由Spring IoC容器管理的对象。@Bean
注解和<bean/>
元素扮演相同的角色。
在一个类上使用@Configuration注解
,其主要用途是做为bean定义的来源。此外, 在同一个类中@Configuration
类容许inter-bean定义经过简单地调用实现依赖关系。最简单的@Configuration
注解类以下:
@Configuration public class AppConfig { @Bean public MyService myService() { return new MyServiceImpl(); } }
上面注解类等价于基于XML配置文件以下:
<beans> <bean id="myService" class="com.howtodoinjava.services.MyServiceImpl"/> </beans>
为了使这样的配置能生效,须要使用AnnotationConfigApplicationContext的帮助
。
public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); MyService myService = ctx.getBean(MyService.class); myService.doStuff(); }
为使组件扫描生效,只须要@Configuration
类注解以下:
@Configuration @ComponentScan(basePackages = "com.howtodoinjava") public class AppConfig { ... }
在上面的示例中com.howtodoinjava包将被扫描,寻找任何带注解@Component
的类,这些类将在容器内登记为Spring bean。
若是你使用以上的方式配置一个web应用程序,那么须要AnnotationConfigWebApplicationContext
类来使之生效。AnnotationConfigWebApplicationContext的使用能够经过配置Spring ContextLoaderListener的
servlet listener,Spring MVC DispatcherServlet
等。
<web-app> <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext --> <context-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value> </context-param> <!-- Configuration locations must consist of one or more comma- or space-delimited fully-qualified @Configuration classes. Fully-qualified packages may also be specified for component-scanning --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>com.howtodoinjava.AppConfig</param-value> </context-param> <!-- Bootstrap the root application context as usual using ContextLoaderListener --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Declare a Spring MVC DispatcherServlet as usual --> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext --> <init-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value> </init-param> <!-- Again, config locations must consist of one or more comma- or space-delimited and fully-qualified @Configuration classes --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>com.howtodoinjava.web.MvcConfig</param-value> </init-param> </servlet> <!-- map all requests for /app/* to the dispatcher servlet --> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping> </web-app>
从Spring 2.5就可使用注解来配置依赖注入。而不是使用XML来描述一个bean的注入,你能够经过使用注解相关的类,方法或字段声明将bean配置的移到注解类自己。
注释注入执行XML注入以前,所以后者配置将会覆盖前者属性链接经过这两种方法。
默认状况下,spring容器没有打开自动注解功能。因此在使用具备spring注解以前,咱们须要在咱们的Spring配置文件启用它。若是你想在Spring应用程序中使用的自动注解,考虑配置文件上加上下面的配置。
<beans> <context:annotation-config/> <!-- bean definitions go here --> </beans>
一旦配置了<context:annotation-config/>
,代表在Spring中您能够开始使用属性,方法和构造函数的自动注入。
一些重要的注解:
一个Spring bean的生命周期很容易理解。当一个bean实例化时可能须要执行一些初始化动做进入使bean达到一个可用的状态。一样,当再也不须要bean时,将bean从容器中移除,可能须要销毁。
Spring beanFactory经过Spring容器负责管理bean的生命周期。bean的生命周期包括能够大致分类为两类的回调方法
Spring框架提供了如下四种方法控制bean的生命周期事件:
例如, customInit()
和 customDestroy()
方法生命周期方法的例子。
<beans> <bean id="demoBean" class="com.howtodoinjava.task.DemoBean" init-method="customInit" destroy-method="customDestroy"></bean> </beans>
spring容器中的bean有5中scope,分别是:
在Spring框架中,当一个bean只用于一个特定属性,建议将它声明为一个内在的bean。内部bean同时支持setter注入属性和构造函数注入“constructor-arg”。
例如,假设一个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="adminis"></property> <property name="address" value="India"></property> <property name="age" value="34"></property> </bean> </property> </bean>
Spring框架不对单例的bean作任何多线程的处理。单例的bean的并发问题和线程安全是开发人员的责任。
而实际上,大多数spring bean没有可变状态(例如服务和DAO的类),这样的话自己是线程安全的。但若是您的bean有可变状态(例如视图模型对象),这就须要你来确保线程安全。
这个问题最简单和明显的解决方案是改变bean Scope,可变的bean从“单例”到“原型”。
Spring提供了四种类型的配置元素集合,以下:
<list>:帮助注入一组值,容许重复。
<set>:帮助注入一组值,不容许重复。
< map>:帮助注入一个K-V的集合,名称和值能够是任何类型的。
<props>:帮助注入一个名称-值对集合,名称和值都是字符串。
让咱们看看每种类型的例子。
<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>
第一个方法是使用<props>标记以下。
<bean id="adminUser" class="com.howtodoinjava.common.Customer"> <!-- java.util.Properties --> <property name="emails"> <props> <prop key="admin">admin@nospam.com</prop> <prop key="support">support@nospam.com</prop> </props> </property> </bean>
也可使用“util:“名称空间建立bean的属性文件,并使用bean的setter方法注入。
<util:properties id="emails" location="classpath:com/foo/emails.properties" />
在spring框架中,在配置文件中设置bean的依赖是一个很好的办法,但spring容器也可以自动注入不一样bean之间的关系。这意味着,经过检查BeanFactory的内容它能够为您的bean自动注入其余bean。
能够为每一个bean指定是否自动注入,所以能够支持一些Bean支持自动注入,而一些bean不会自动注入。
下面从XML配置文件摘录了自动根据名称注入的bean。
<bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAOImpl" autowire="byName" />
除了提供的自动装配模式bean配置文件,也能够在bean类中指定自动装配使用 @Autowired
注释。
注意:在bean类使用@Autowired注解
,您必须在spring应用程序中先启用下面的注解。
<context:annotation-config />
也能够经过在配置文件使用AutowiredAnnotationBeanPostProcessor
bean来完成。
<bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
如今,当注释配置已经启用,您能够自由使用@Autowired来
自动注入bean依赖关系,以你喜欢的方式。
@Autowired public EmployeeDAOImpl ( EmployeeManager manager ) { this.manager = manager; }
在Spring有五个自动注入模式。让咱们逐个讨论。
要启用@Autowired
,你必须注册AutowiredAnnotationBeanPostProcessor
,你能够用两种方式。
1. 在bean配置文件使用<context:annotation-config >
。
<beans> <context:annotation-config /> </beans>
2. 直接将AutowiredAnnotationBeanPostProcessor放到
bean配置文件。
<beans> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> </beans>
在大规模的应用程序中,IoC容器中可能会有成百上千的bean声明,以及它们之间的依赖关系一般是很是复杂的。
setter注入的缺点之一是,很难给你检查出所需的全部属性是否已经注入。
为了克服这个问题,您能够设置bean的“dependency-check”属性,能够设置四个属性的其中之一即 none, simple, objects or all (没有一个是默认选项)。
在现实生活中应用程序中,您将不会感兴趣检查全部上下文中的bean属性配置文件。而你想要检查一些特定的bean是否已设置特定的属性。在这种状况下,Spring的依赖项检查功能将再也不适用,。
为了解决这个问题,您可使用@Required
注解。在bean属性使用@Required
注解的setter方法类文件以下:
public class EmployeeFactoryBean extends AbstractFactoryBean<Object> { private String designation; public String getDesignation() { return designation; } @Required public void setDesignation(String designation) { this.designation = designation; } //more code here }
RequiredAnnotationBeanPostProcessor
是一个spring bean后置处理程序,检查@Required注解的
全部的bean属性是否已设置。使用这个bean属性检查后置处理程序,您必须注册在Spring IoC容器中。
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
若是@Required注解的任何属性
没有设置,这个bean的处理器会抛出一个BeanInitializationException
异常。
@Autowired
注解提供了更细粒度的控制,以及应该如何完成自动注入。@Autowired
注解和@Required注解
同样,可用于bean的自动注入,它能够做用于构造方法,属性或具备任意名称和/或多个参数的方法。
例如,您可使用@Autowired
注解的setter方法来代替在XML配置文件中的<property>
元素。当Spring找到一个@Autowired
注解的方法,它尝试使用byType自动注入的方法。
您能够将@Autowired应用到
构造方法。一个构造方法使用@Autowired注解
代表,即便在XML文件没有配置bean的<constructor-arg>
元素,当建立bean时,构造方法也会自动注入。
public class TextEditor { private SpellChecker spellChecker; @Autowired public TextEditor(SpellChecker spellChecker){ System.out.println("Inside TextEditor constructor." ); this.spellChecker = spellChecker; } public void spellCheck(){ spellChecker.checkSpelling(); } }
没有构造方法参数的配置。
<beans> <context:annotation-config/> <!-- Definition for textEditor bean without constructor-arg --> <bean id="textEditor" class="com.howtodoinjava.TextEditor"> </bean> <!-- Definition for spellChecker bean --> <bean id="spellChecker" class="com.howtodoinjava.SpellChecker"> </bean> </beans>
@Qualifier限定哪一个bean应该被自动注入
。当Spring没法判断出哪一个bean应该被注入时,@Qualifier注解有助于消除歧义bean的自动注入。
参见下面的例子,
public class Customer
{
@Autowired
private Person person;
}
咱们有两个bean定义为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 知道哪一个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应该被autowired的。
public class Customer { @Autowired @Qualifier("personA") private Person person; }
有如下几点明显的差别:
ObjectCurrentlyInCreationException
。因此Spring能够经过setter注入,从而解决循环依赖的问题。Spring的ApplicationContext具备代码层上
支持事件和监听器的功能。咱们能够建立bean监听经过ApplicationContext发布的事件。ApplicationContext里的事件处理经过提供ApplicationEven
t类和ApplicationListener
接口来完成。因此若是一个bean实现了ApplicationListener接口
,当一个ApplicationEvent
发布到ApplicationContext时,该bean将接到
通知。
public class AllApplicationEventListener implements ApplicationListener < ApplicationEvent > { @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { //process event } }
Spring提供了如下5标准事件:
ConfigurableApplicationContext
接口的refresh()方法来触发。除了上面的事件,您能够经过扩展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 } }
发布这个事件:
CustomApplicationEvent customEvent = new CustomApplicationEvent( applicationContext, "Test message" ); applicationContext.publishEvent ( customEvent );
在FileSystemResource中
你须要给出spring-config.xml
(Spring配置)文件相对于您的项目的相对路径或文件的绝对位置。
在ClassPathResource中Sping
查找文件使用ClassPath,所以
spring-config.xml
应该包含在类路径下。
一句话,ClassPathResource在类路径下搜索和FileSystemResource在文件系统下搜索。
有不少不一样的设计模式,但有一些明显的:
JmsTemplate
, JpaTemplate
.DispatcherServlet
,确保传入请求被分派到你的控制器。BeanFactory
/ ApplicationContext的核心
概念。原文:https://howtodoinjava.com/interview-questions/top-spring-interview-questions-with-answers/