史上最详细的Spring面试题(附答案)

1、简单介绍一下Spring?
Spring 是个java企业级应用的开源开发框架。Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用。Spring 框架目标是简化Java企业级应用开发,并通过POJO为基础的编程模型促进良好的编程习惯。
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实现。

2、Spring有哪些优点?
(1)spring属于低侵入式设计,代码的污染极低;
(2)spring的DI机制将对象之间的依赖关系交由框架处理,减低组件的耦合性;
(3)Spring提供了AOP技术,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,从而提供更好的复用。
(4)spring对于主流的应用框架提供了集成支持。

(1)轻量:Spring 是轻量的,基本的版本大约2MB。
(2)控制反转:Spring通过控制反转实现了松散耦合。
(3)面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
(4)容器:Spring 包含并管理应用中对象的生命周期和配置。
(5)MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
(6)事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务,下至全局事务(JTA)。
(7)异常处理:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。

3、讲一讲对Spring中的AOP技术的理解
OOP面向对象其中一个优势就是继承,父类的代码可以被子类所复用,但平级关系类中使用相同的功能代码时会出现大量代码的重复,不利于各个模块的复用,这种情况可以使用AOP技术来解决。
AOP称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的那些公共行为和逻辑进行抽取并封装为一个可重用的模块,这个模块被命名为“切面(Aspect)”。切面可以减少系统中的重复代码,降低模块间的耦合度,同时提高系统的可维护性。可用于权限认证、日志、事务处理。
AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP把软件系统分为两个部分:
核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

4、介绍一下使用JDK Proxy类如何实现动态代理?
有业务接口,有实现业务接口的业务类,还需要创建实现了InvocationHandler接口的MyInvocationHandler类。
InvocationHandler 的 invoke(Object proxy,Method method,Object[] args):proxy是最终生成的代理实例; method 是被代理目标实例的某个具体方法; args 是被代理目标实例某个方法的具体入参, 在方法反射调用时使用。
使用如下代码创建代理类:
Proxy.newProxyInstance(Test1.class.getClassLoader(),
dangdangBook.getClass().getInterfaces(), handler);

5、介绍一下静态和动态代理以及区别?
AOP技术的原理是“代理模式”,AOP代理主要分为静态代理和动态代理。
(A)普通的类和接口实现静态代理,代理类绑死了接口。
另外也可以使用AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。
参考网址:
Java 静态代理 AspectJ 使用
https://www.jianshu.com/p/aa293edba2e4
Spring AOP,AspectJ, CGLIB 有点晕
https://www.jianshu.com/p/fe8d1e8bd63e

(B)Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。动态代理可以使用JDK Proxy和CGLIB来实现。
回答思路可以先介绍静态代理的缺点,再介绍动态代理的优点。

(C)静态代理与动态代理区别在于生成AOP代理对象的时机不同。静态代理在编译时创建了代理类,而动态代理是在运行时创建了代理类。

6、当业务类实现或未实现接口时,在创建代理类时的区别是什么?
① 实现接口:JDK动态代理只支持对接口进行代理,不支持对类进行代理。核心内容是InvocationHandler接口和Proxy类,InvocationHandler 通过在invoke()方法中使用反射技术调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
② 未实现接口:如果业务类没有实现接口,那么Spring AOP会选择使用CGLIB实现动态代理,代理类继承自业务类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

7、介绍一下对Spring IoC的理解:

(1)IOC是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。DI依赖注入和IOC控制反转是同一个概念的不同角度的描述,即:应用程序在运行时依赖IoC容器来动态注入对象需要的外部资源。
(2)最直观的表达就是,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。
(3)Spring的IOC有三种注入方式 :构造器注入、setter方法注入、根据注解注入。

IoC让相互协作的组件保持松散的耦合,而AOP编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件。

IoC不是什么技术,而是一种设计思想。在java的开发过程中。ioc意味着将你设计好的对象交给容器控制,而不是传统的在对象内部直接控制。理解“谁控制谁,控制什么,为何是反转(有反转是不是有正转),反转了哪些”

 谁控制谁,控制什么:传统java se程序设计,我们直接在对象内部通过new进行创建对象;而IOC有专门的容器创建对象,由容器来控制对象;谁控制谁?IOC容器控制对象;控制了什么?主要控制了外部资源获取(不只是对象,包括文件)
 为何是反转,哪些反转了:有反转就有正转,传统的应用程序是由我们在对象中主动控制去直接获取依赖对象,也就是正转;反转就是由容器帮我们创建以及注入依赖对象;为何是反转,因为是由容器帮我们查找及注入对象,对象只是被动的接受;
哪些反转了:依赖对象的获取方式被反转了

IOC是一种设计思想(思想的转变),之前所有创建对象的操作是由程序员自己new,现在交给了spring,由spring帮我们创建对象,注入之类的。控制反转,控制是指 ioc提供的容器控制类的对象,反转是指转交给spring来负责。最大的作用就是解耦(降低耦合性)

IOC是一种叫做“控制反转”的设计思想。
1、较浅的层次——从名字上解析
“控制”就是指对 对象的创建、维护、销毁等生命周期的控制,这个过程一般是由我们的程序去主动控制的,如使用new关键字去创建一个对象(创建),在使用过程中保持引用(维护),在失去全部引用后由GC去回收对象(销毁)。
“反转”就是指对 对象的创建、维护、销毁等生命周期的控制由程序控制改为由IOC容器控制,需要某个对象时就直接通过名字去IOC容器中获取。
2、更深的层次——提到DI,依赖注入,是IOC的一种重要实现
一个对象的创建往往会涉及到其他对象的创建,比如一个对象A的成员变量持有着另一个对象B的引用,这就是依赖,A依赖于B。IOC机制既然负责了对象的创建,那么这个依赖关系也就必须由IOC容器负责起来。负责的方式就是DI——依赖注入,通过将依赖关系写入配置文件,然后在创建有依赖关系的对象时,由IOC容器注入依赖的对象,如在创建A时,检查到有依赖关系,IOC容器就把A依赖的对象B创建后注入到A中(组装,通过反射机制实现),然后把A返回给对象请求者,完成工作。
3、IOC的意义何在?
IOC并没有实现更多的功能,但它的存在使我们不需要很多代码、不需要考虑对象间复杂的耦合关系就能从IOC容器中获取合适的对象,而且提供了对 对象的可靠的管理,极大地降低了开发的复杂性。

8、BeanFactory和ApplicationContext有什么区别?

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

(1)两者具有继承关系
BeanFactory:是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。ApplicationContext接口作为BeanFactory的子接口,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能:
A.继承MessageSource,因此支持国际化。
B.统一的资源文件访问方式。
C.提供在监听器中注册bean的事件。
D.同时加载多个配置文件。
E.载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。

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

(3)BeanFactory通常以手写代码的方式被创建。
ApplicationContext还能以声明的方式创建,如使用ContextLoader,在web.xml中进行配置,代码如下:

org.springframework.web.context.ContextLoaderListener

继承关系:
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {

(4)BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:
BeanFactory需要手动注册,代码如下:
DefaultListableBeanFactory c;
c.addBeanPostProcessor(beanPostProcessor);

方法为public:
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor)

ApplicationContext则是自动注册。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

BeanFactory:
是spring里面最底层的接口,提供了最简单的容器的功能,只提供实例化对象和获取对象
applicationContext:
应用上下文,继承了BeanFactory接口(上一个的子接口),提供了更多的功能
1.ClassPathXmlApplicationContext 从 classpath 加载 spring 的配置文件
2.FileSystemApplicationContext 从系统文件加载 spring 的配置文件
3.AnnotationConfigApplicationContext 获取基于注解的 spring 容器对象
4.XmlWebApplicationContext 在web环境中获取 spring 容器对象

9、请解释Spring Bean的生命周期?
首先说一下Servlet的生命周期:实例化,初始init,接收请求service,销毁destroy;
Spring上下文中的Bean生命周期也类似,如下:
(1)实例化Bean:
对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。
(2)设置对象属性(依赖注入):
实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成依赖注入。
(3)处理Aware接口:
接着,Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean:
①如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setB

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值