Spring 框架面试题总结(待续更新中...)
来源:互联网 发布:网站源码怎么打开网页 编辑:程序博客网 时间:2024/09/21 09:04
一. 什么是Spring?
答:Spring的核心是一个轻量级的容器(Container),它是实现IoC(Inversion of Control)容器和非侵入性(No intrusive)的框架,并提供AOP(Aspect-oriented Programming)的实现方式,提供对持久层(Persistence)、事务(Transcation)的支持;提供MVC Web框架的实现,并对一些常用的企业服务API提供了一致的模型封装,是一个全方位的应用程序框架,除此之外,对现存的各种框架(Structs、JSF、Hibernate、Ibatis、Webwork等),Spring也提供了与他们相整合的方案。
细化:
1、Spring的核心是一个轻量级(Lightweight)的容器(Container)。
2、Spring是实现IoC(Inversion of Control)容器和非入侵性(No intrusive)的框架。
3、Spring提供AOP(Aspect-oriented programming)的实现方式,把应用业务逻辑和系统服务分开。
4、Spring提供对持久层(Persistence)、事物(Transcation)的支持。
5、Spring供MVC Web框架的实现,并对一些常用的企业服务API(Application Interface)提供一致的模型封装。
6、Spring提供了对现存的各种框架(Structs、JSF、Hibernate、Ibatis、Webwork等)相整合的方案。
总之,Spring是一个全方位的应用程序框架。
二、Spring的核心
1、IoC/DI(控制反转/依赖注入):
1)控制反转可以分开来解读,控制和反转-> 首先控制什么?对什么进行控制? 其实此处的控制指的是程序中的一些对象或者变量的控制权,在传统的程序中都是由应用程序自己控制对象创建或者变量赋值,这是一种主动式的控制,导致组件之间的完全耦合;现在将一些对象或者变量的创建控制权交给一个叫做Ioc容器的东西,由这个容器来控制应用程序中所需要的资源,这样就变成了被动的控制,对组件之间的关系进行解耦,所以所谓的反转就是将控制权由应用程序转交到Ioc容器。
2)依赖注入:同样将DI分开来解读,依赖和注入-> 首先依赖什么?谁依赖谁? 其实应用程序中所需要的资源创建和获取都是要依赖于Ioc容器,需要IoC容器装配类之间的关系,即应用程序依赖于IoC容器的装配功能;相反,注入就是IoC容器向应用程序中进行注入应用程序所需要的资源,由应用程序主动装配对象的依赖变应用程序被动接受依赖,所以IoC容器也叫DI容器。
综上所述,控制权的主动与被动式其实都是相对于(参考物)IoC容器来说的,也可以将IoC模式看做是工厂模式的升华,不同的是Spring中的控制反转所用到的是Java的“反射”技术,通过在XML文件中定义应用程序所需要的类,再由IoC容器根据xml文件创建这些对象。所以这也形成了工厂与对象生成这两者独立分隔开,目的就是提高灵活性和可维护性。之所以将对象生成放到xml文件中,如果我们想要换一个实现的类将变得很简单,只需要修改xml文件即可。
2、AOP(面向切面编程):将具体的通用的应用从业务逻辑中分离出来,各自做各自专业的事情。
1)切面:简单的理解就是一个类,每个或者对象
2)连接点:类中的方法(可以切入的地方)
3)通知:切面在某个连接点执行的操作(分为: Before advice , After returning advice , After throwing advice , After (finally) advice , Around advice );
4)切入点:符合切点表达式的连接点,也就是真正被切入的地方
5)引入:
6)目标对象:
三、Spring能做什么?
四、Spring注入Bean的方式
(1)设值注入(set方法)
(2)构造器注入
(3)工厂方法
Spring加载Bean的流程:
(1)创建一个上下文context = createApplicationContext;
(2)context中都会有一个BeanFactory(默认是DefaultListableBeanFactory),在该类的子类类xmlBeanFactory中进行xml文件的解析;
(3)在类XmlBeanDefinitionParser 中用Dom解析xml文件(DefaultXmlBeanDefinitionParser),解析xml文件中所有bean,并将bean放到BeanDefinitionHolder中,封装成BeanDefinition;
(4)再进行bean的注册,具体在BeanDefinitionReaderUtils类调用DefaultListableBeanFactory类的registerBeanDefinition进行bean的注册,在这里用了一HashMap存放bean,其中用Beanname作为键值,其封装好的beanDefinition作为值。还有用一个List存放所有的bean的名字。
设值注入和构造器注入的区别
1) 在设置注入需要该Bean包含这些属性的setter方法;
2) 与传统的JavaBean的写法更相似,程序开发人员更容易理解、接收。通过setter方法设定依赖关系显得更加只管;
3) 对于复杂的依赖关系,如果采用构造注入,会导致构造器参数列表复杂,难以阅读。Spring在创建Bean实例时,需要同时实例化其它依赖的全部实例,因而导致性能下降。而使用设值注入,则能避免这些问题;
4) 尤其是在某些属性可选的情况况下,多参数的构造器显得更加复杂;
但是在其他的场景,构造器注入显得更好的性能:
1) 构造注入需要该Bean包含带有这些属性的构造器;
2) 构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入;
3) 对于依赖关系无需变化的Bean,构造注入更有用处。因为没有Setter方法,所有的依赖关系全部在构造器内设定。因此,无需担心后续的代码对依赖关系产生破坏
4) 依赖关系只能在构造器中设定,则只有组件的创建者才能改变组件的依赖关系。对组件的调用者而言,组件内部的依赖关系完全透明,更符合高内聚的原则.
(1)在使用设值注入时有可能还不能保证某种依赖是否已经被注入,也就是说这时对象的依赖关系有可能是不完整的。而在另一种情况下,构造器注入则不允许生成依赖关系不完整的对象。
(2)在设值注入时如果对象A和对象B互相依赖,在创建对象A时Spring会抛出sObjectCurrentlyInCreationException异常,因为在B对象被创建之前A对象是不能被创建的,反之亦然。所以Spring用设值注入的方法解决了循环依赖的问题,因对象的设值方法是在对象被创建之前被调用的。
注:采用以设值注入为主,构造注入为辅的注入策略。对于依赖关系无需变化的注入,尽量采用构造注入;而其他的依赖关系的注入,则考虑采用设值注入。
五、Bean的生命周期(以BeanFactory)
1) Bean的建立,由BeanFactory读取Bean定义文件,并创建Bean实例;
2) 执行Bean的属性注入,Setter注入;
3) 如果Bean类实现了org.springframework.beans.factory.BeanNameAware接口,则执行其setBeanName方法;
4) 如果Bean类实现了org.springframework.beans.factory.BeanFactoryAware接口,则执行其setBeanFactory方法;
5) 如果容器中有实现org.springframework.beans.factory.BeanPostProcessors接口的实例,则任何Bean在初始化之前都会执行这个实例的processBeforeInitialization()方法;
6) 如果Bean类实现了org.springframework.beans.factory.InitializingBean接口,则执行其afterPropertiesSet()方法;
7) 调用Bean的初始化方法”init-method” (!!注意,init-method方法没有参数);
8) 如果容器中有实现org.springframework.beans.factory.BeanPostProcessors接口的实例,则任何Bean在初始化之后都会执行这个实例的processAfterInitialization()方法;
9) 使用Bean做一些业务逻辑….
10) 使用完,容器关闭,如果Bean类实现了org.springframework.beans.factory.DisposableBean接口,则执行它的destroy()方法;
11) 在容器关闭时,可以在Bean定义文件中使用“destory-method”定义的方法,销毁Bean (!!注意,destory-method方法没有参数);
ApplicationContext中bean的生命周期也是类似的。
六、BeanFactory 和ApplicationContext的区别
- 首先BeanFactory和ApplicationContext都是接口,并且ApplicationContext是BeanFactory的子接口。
- 其次BeanFactory是Spring中最底层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能,
ApplicationContext(应用上下文)它是Spring的一个更高级的容器,提供了更多的有用的功能;
1)ApplicationContext继承了BeanFactory接口,所以,ApplicationContext也能像BeanFactory从容器中得到Bean(继承至 ListableBeanFactory);
2)ApplicationContext提供的额外的功能:
国际化的功能,消息发送、响应机制(继承至MessageSource );统一加载资源的功能(继承至ResourceLoader);强大的事件机制( 继承至ApplicationEventPublisher);对Web应用的支持() - 它们的加载方式不同:
1) BeanFactory采用的是延迟加载的形式来注入Bean,即只有在使用某个bean的时候,才对该Bean进行加载实例化.好处是节约内存,缺点是速度比较慢.
2) ApplicationContext则相反的,它是在Ioc容易启动时就一次性创建所有的Bean,这样的好处是可以马上发现Spring配置文件中的错误。坏处就是浪费内存。
ApplicationContext的三种较常见的实现方式:
1) ClassPathXmlApplicationContext:从classpath的xml配置文件中读取上下文,并生成上下文定义,应用程序上下文从程序环境中取得。
ApplicationContext context = new ClassPathXmlApplicationContext("****.xml");
2) FileSystemXmlApplicationContext:由文件系统中的xml配置文件读取上下文。
ApplicationContext context = new FileSystemXmlApplicationContext("****.xml");
3) XmlWebApplicationContext:由Web应用的Xml文件读取上下文。
七、Spring Bean的作用域
1) Singleton: 这是默认的作用域,这种范围确保不管接受多少个请求,每个容器中只有一个bean的实例,单例模式有BeanFactory自身维护;
2) Prototype: 原形范围与单例范围相反,为每一个bean请求提供一个实例;
3) Request: 在请求bean范围内会为每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收;
4) Session: 与请求范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效;
5) global-session: global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。
八、Bean的自动装配模式
- no: spring默认的设置,在该设置下自动装配是关闭的,开发者需要在配置文件中用标签明确依赖关系;
- byName: 该选项可以根据bean名称设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
- byType: 该选项可以根据bean类型设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的类型自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
- constructor: 构造器自动装载,仅仅适用于与有构造器相同参数的bean,如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
- autodetect: 该模式自动探测使用构造器自动装配或者byType自动装配。先尝试找合适的带参数的构造函数,若没有则自动选择byType的自动装配模式。
基于注解的自动装配,spring默认是关闭注解模式的,所以需要在配置文件中设置
九、各种注解的解释
@Required: 验证bean是否被正确的设置了,需要在Ioc容器中注册RequiredAnnotationBeanPostProcessor,它是Spring中的后置处理用来验证被@Required 注解的bean属性是否被正确的设置了,若没有属性被@Required注解过的话,后置处理器会抛出一个BeanInitializationException异常。
@AutoWired: 该注解用于在bean的设值方法上自动装配bean的属性,一个参数或者带有任意名称或带有多个参数的方法。(尝试用byType 自动装配)
- @Qualifer: 该注解一般和@AutoWired一起使用,用于帮助Ioc容器能知道当前注解的属性应该自动装配哪一个。(对于在xml文件中定义了多个同类的bean,但是id不同,若单单用@AutoWired进行注解,Ioc容器无法分辨出应该自动装配哪一个bean)
十、Spring 中的所有哪些不同类型的事件?
Spring的ApplicationContext提供了支持事务和代码中添加监听器的功能。
可以创建一个bean其实现ApplicationListener接口(类型是ApplicationEvent),当一个ApplicationEvent 被发布后,bean就自动被通知,并且在方法onApplicationEvent(…)方法中处理该事件。
public class AllApplicationEventListener implements ApplicationListener < ApplicationEvent >{ @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { //process event }}
在Spring中有5中标准的事件:
1. 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布,也可以在调用ConfigurableApplicationContext接口中的refresh()方法时被触发。
2. 上下文开始事件(ContextStartedEvent): 当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时被触发。
3. 上下文停止事件(ContextStoppedEvent): 当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
4. 上下文关闭事件(ContextClosedEvent): 当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
5. 请求处理事件(RequestHandledEvent): 在Web应用中,当一个http请求(request)结束触发该事件。
spring也让用户可以自定义事件类型,继承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);
十一、Spring 框架中都用到了哪些设计模式?
- 代理模式—在AOP和remoting中被用的比较多。
- 单例模式—在spring配置文件中定义的bean默认为单例模式。
- 模板方法—用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
- 前端控制器—Spring提供了DispatcherServlet来对请求进行分发。
- 视图帮助(View Helper )—Spring提供了一系列的JSP标签,高效宏来辅助将分散的代码整合在视图里。
- 依赖注入—贯穿于BeanFactory / ApplicationContext接口的核心理念。
- 工厂模式—BeanFactory用来创建对象的实例。
- Spring 框架面试题总结(待续更新中...)
- Spring 框架面试题总结
- java面试题总结(更新中)
- php面试题总结(更新中。。。)
- Swift面试题总结(持续更新中)
- Android 面试题总结(持续更新中)
- Android经典面试题总结(未完待续)
- 常见面试题 (待续)
- 百度面试题(总结+更新)
- 面试题总结(持续更新)
- 面试题总结(有空就更新)
- spring面试题总结
- Spring面试题总结
- Spring面试题总结
- Spring 面试题总结
- spring框架面试题(待定)
- 面试题整理(更新中)
- 面试题汇集(更新中)
- 监管层应介入区块链规则制定
- Hive安装、配置,HQL,实践
- POJ1753
- leetcode1 || TwoSum
- Educational Codeforces Round 12 E. Beautiful Subarrays 预处理前缀+字典树优化★ ★
- Spring 框架面试题总结(待续更新中...)
- 软件测试——杯子、网页登入界面
- 可复制的成功学
- [console] early printk实现流程
- Mybatis源码之Statement处理器PreparedStatementHandler(五)
- Hibernate hiberante query language(一对多的操作)
- 不要混淆电子货币和加密货币概念
- JAVA基础知识点梳理六:static相关
- 看好区块链技术应用于P2P行业征信