Spring的两大核心是什么?谈一谈你对IOC的理解? 谈一谈你对DI的理解? 谈一谈你对 AOP 的理解?(必会)
1. Spring 的两大核心是:IOC(控制翻转)和 AOP(面向切面编程) DI(依赖注入)
2. IOC 的意思是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和 时机是由自己把控的,而现在这种权力转移到 Spring 容器中,并由容器根据配置文件去创 建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。最 直观的表达就是,IOC 让对象的创建不用去 new 了,可以由 spring 根据我们提供的配置文 件自动生产,我们需要对象的时候,直接从 Spring 容器中获取即可. Spring 的配置文件中配置了类的字节码位置及信息, 容器生成的时候加载配置文件识 别字节码信息, 通过反射创建类的对象. Spring 的 IOC 有三种注入方式 :构造器注入, setter 方法注入, 根据注解注入。
3. DI 的意思是依赖注入,和控制反转是同一个概念的不同角度的描述,即应用程序在 运行时依赖 Io c 容器来动态注入对象需要的外部资源。
4. AOP,一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关, 但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被 命名为“切面”(Aspect). SpringAOP 使用的动态代理,所谓的动态代理就是说 AOP 框 架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个 AOP 对象,这个 AOP 对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
5. Spring AOP 中的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理:
(1)JDK 动态代理只提供接口代理,不支持类代理,核心 InvocationHandler 接口和 Proxy 类,InvocationHandler 通过 invoke()方法反射来调用目标类中的代码,动态地将 横切逻辑和业务编织在一起,Proxy 利用 InvocationHandler 动态创建一个符合某一接口 的的实例, 生成目标类的代理对象。
(2) 如果代理类没有实现 InvocationHandler 接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库, 可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从 而实现 AOP。CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final, 那么它是无法使用 CGLIB 做动态代理的。
Spring 的生命周期?(高薪常问)
1. 实例化一个 Bean,也就是我们通常说的 new
2. 按照 Spring 上下文对实例化的 Bean 进行配置,也就是 IOC 注入
3. 如果这个 Bean 实现 dao 了 BeanNameAware 接口,会调用它实现的 setBeanName(String beanId)方法,此处传递的是 Spring 配置文件中 Bean 的 ID
4. 如果这个 Bean 实现了 BeanFactoryAware 接口,会调用它实现的 setBeanFactory(), 传递的是 Spring 工厂本身(可以用这个方法获取到其他 Bean)
5. 如果这个 Bean 实现了 ApplicationContextAware 接口,会调用 setApplicationContext(ApplicationContext)方法,传入 Spring 上下文,该方式同样可 以实现步骤 4,但比 4 更好,以为 ApplicationContext 是 BeanFactory 的子接口,有更多 的实现方法
6. 如果这个 Bean 关联了 BeanPostProcessor 接口,将会调用 postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor 经常被 用作是 Bean 内容的更改,并且由于这个是在 Bean 初始化结束时调用 After 方法,也可用 于内存或缓存技术
7. 如果这个 Bean在 Spring 配置文件中配置了 init-method 属性会自动调用其配置的初始 化方法
8. 如果这个 Bean 关联了 BeanPostProcessor 接口,将会调用 postAfterInitialization(Object obj, String s)方法 注意:以上工作完成以后就可以用这个 Bean 了,那这个 Bean 是一个 single 的,所以 一般情况下我们调用同一个 ID 的 Bean 会是在内容地址相同的实例
9. 当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 接口,会 调用其实现的 destroy 方法
10. 最后,如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其 配置的销毁方法
Spring 支持 bean 的作用域有几种吗? 每种作用域是什么样的?(必会)
Spring 支持如下 5 种作用域:
(1)singleton:默认作用域,单例 bean,每个容器中只有一个 bean 的实例。
(2)prototype:为每一个 bean 请求创建一个实例。
(3)request:为每一个 request 请求创建一个实例,在请求完成以后,bean 会失效 并被垃圾回收器回收。
(4)session:与 request 范围类似,同一个 session 会话共享一个实例,不同会话 使用不同的实例。
(5)global-session:全局作用域,所有会话共享一个实例。如果想要声明让所有会 话共享的存储变量的话,那么这全局变量需要存储在 global-session 中。
BeanFactory 和 ApplicationContext 有什么区别(了解)
BeanFactory:
Spring 最顶层的接口,实现了 Spring 容器的最基础的一些功能, 调用起来比较麻 烦, 一般面向 Spring 自身使用 BeanFactory 在启动的时候不会去实例化 Bean,从容器中拿 Bean 的时候才会去 实例化
ApplicationContext:
是 BeanFactory 的子接口,扩展了其功能, 一般面向程序员身使用 ApplicationContext 在启动的时候就把所有的 Bean 全部实例化了
写在最后
本篇分享了四道Spring的面试题,未来还会继续分享相关资料。笔者小,中,大厂均有面试经验,每日分享全栈知识,希望和大家共同进步。