Spring常见面试题

一、SpringAOP面向切面编程

1.概念介绍:
AOP:Aspect Oriented Programming(面向切面编程),通过动态代理技术,对代码中的横向功能进行提取或增强。

这里的横向功能指与业务无关的却共同调用的逻辑,如日志、事务等。

我们知道JAVA是面对对象编程,有封装/继承/多态等特性,其中继承用于解决纵向的代码重复。而AOP就是减少横向的代码重复。

2.代理模式实现步骤
(1)声明接口:注册需要被监听行为名称
(2)接口实现类: 扮演被监控的类,负责被监听方法实现细节
(3)InvocationHanler接口实现类:
a.次要业务/增强业务;
b.将次要业务与被监听方法绑定执行
(4)代理监控对象:被监控类内存地址,被监控类实现的接口,
InvocationHandler实现类的实例对象

3.SpringAOP动态代理实现方式
(1)基于JDK:基于接口。
JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理
(2)使用CGLib:基于继承父类生成的代理类。
Cglib是动态代理利用asm的开源包,对代理对象的Class文件加载进来,通过修改其字节码生成的子类来处理

具体代码使用可参考:https://blog.youkuaiyun.com/qq_42807370/article/details/87354522

4.SpringAOP和AspectJAOP区别
SpringAOP只支持方法级编织,属于动态织入(动态代理);
AspectJAOP可以编织字段/方法/构造函数/最终类/静态初始值,属于静态织入(编译期class文件织入),性能也更好,但是使用起来更麻烦(1.xml方式 2注解方式-需要jar包)

二、SpringIOC控制反转

1.IOC
IOC(控制反转):指对象的创建权力由程序反转给Spring框架。通过反射实现。

2.DI
DI(依赖注入):在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中。是IOC思想的具体实现。

为什么要使用依赖注入:我们的程序在编写时,通过控制反转,降低了依赖关系,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。比如我们的业务层仍会调用持久层的方法,可使用 spring框架的依赖注入把持久层对象传入业务层,而不用我们自己去获取。

三、SpringBean生命周期

1.SpringBean的生命周期
(1)实例化 bean 对象:通过反射调用Bean的构造方法实例化Bean
(2)属性注入:通过反射注入Bean的属性值
(3)初始化 bean 对象
其中初始化Bean对象分为如下几步:
a.激活Aware方法:
①BeanNameAware.setBeanNameAware()
②BeanFactoryAware.setBeanFactoryAware()
b.BeanFactoryPostProcessor.postProcessBeanFactory();
c.BeanPostProcessor.postProcessBeforeIntialization();
c.调用init方法;
d.BeanPostProcessor.postProcessAfterIntialization();
e.注册需要执行销毁方法的Bean

这里简单描述一下:
首先Bean的初始化分为三步–
通过反射调用Bean的构造方法实例化–>通过反射注入属性–>初始化bean对象;
然后初始化Bean对象分为下面几步–
激活aware方法,包括BeanNameAware和BeanFactoryAware–>
调用Bean工厂的后置处理器,加工Bean实例–>
调用Bean的后置处理器,在Bean初始化前后进行拦截,在此过程中,bean完成了初始虎啊–>
注册需要执行销毁方法的Bean

2.BeanFactoryPostProcessor与BeanPostProcessor区别:
前者是beanFactory 的后置处理器,把BeanDefinition加工变成bean实例,比如实现了该接口的PropertyPlaceHolderConfigurer用于替换BeanDefinition中的占位符(${})中的内容;
后者是bean 后置处理器,bean 创建对象初始化前后进行拦截工作的。比如实现该接口的AutowiredBeanPostProcessor开启Bean实例的@Autowired注解的功能。

3.@Autowired和@Resource的区别:
前者是根据java类型获取实例,限制是在同一spring容器中只能有一个实例;后者优先通过Bean标签名称获取实例,没有名称也可以通过类型匹配,建议使用后者,属于j2ee,减少与spring耦合。如果有多个类型相同的bean,可以使用@Qualifier(“XXX”)可以通过XXX名称来确定。

四、Spring如何解决循环依赖

1.Spring三级缓存机制
第一级缓存(也叫单例池):Map<String, Object> singletonObjects,存放已经经历了完整生命周期的 Bean 对象
第二级缓存:Map<String, Object> earlySingletonObjects,存放早期暴露出来的 Bean 对象,Bean 的生命周期未结束(属性还未填充完),可能是代理对象,也可能是原始对象。
第三级缓存:Map<String, ObjectFactory<?>> singletonFactories,存放可以生成 Bean 的工厂,工厂主要用来生产bean的代理对象
–三级缓存用于解决AOP后的对象不是原对象的问题

2.Spring如何解决循环依赖
在这里插入图片描述
简单解释一下:
首先Spring是通过递归的方式获取目标bean及其所依赖的bean的;
Spring实例化一个bean的时候,是分两步进行的,首先实例化目标bean,然后为其注入属性。
结合这两点,可知当AB循环依赖时,A先实例化A对象,并放入三级缓存,依赖属性b就获取B对象,此时B也实例化B对象放入三级缓存,当B也依赖属性a时会把刚刚实例化的半成品A返回以完成B的实例化,最后注入属性b,返回成品A对象。

五、Spring事务传播

1.概念介绍
事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播。

2.Spring的七种事务传播类型
一般使用@Transaction注解使用事务
(1)PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
(2)PROPAGATION_SUPPORTS:支持当前事务(加入),如果当前没有事务,就以非事务方式执行。
(3)PROPAGATION_MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
(4)PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
(5)PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
(6)PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
(7)PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

3.常见的嵌套场景
(1)如果A的事务为required,B的事务的new,在A中调用B,如果A抛异常回滚了,B不会回滚,因为它创建了属于自己的事务,挂起了A。
(2)A不变,将B的事务改为required,在A中调用B,如果A抛异常回滚了,B也会回滚,因为它会加入事务,此时B的事务相当于不加事务
(3)A不变,将B的事务改为NOT_SUPPORTED,在A中调用B,如果A抛异常回滚了,B也不会回滚

六、Spring中用到的设计模式

1.工厂模式:BeanFactory
2.单例模式:Bean默认为单例模式
3.代理模式:AOP
4.模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
5.包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
6.观察者模式: Spring 事件驱动模型ApplicationListener就是观察者模式很经典的一个应用。
7.适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller。

单例模式几种实现方式(复习一下):
(1)懒汉式,延迟加载,但这几个里唯一线程不安全的
(2)饿汉式,常用,效率高
(3)双重检查锁,volatile防止指令重排序。对象创建分三个步骤:分配内存、初始化对象、分配地址;多线程下重排序可能导致先分配地址,再初始化对象。
(4)枚举,线程安全且可以防止反序列化

七、SpringMVC

1.SpringMVC简介
SpringMVC是基于Spring实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,使用了MVC的架构模式思想,将Web层进行指责解耦
M:Model对象实例 V:View视图 C:Controller控制器

2.SpringMVC架构流程:
(1)用户发送请求至前端控制器DispatcherServlet
(2)DispatcherServlet收到请求调用HandlerMapping处理器映射器。
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
(4)DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
(5)HandlerAdapter执行处理器(handler,也叫后端控制器)。
(6)Controller执行完成返回ModelAndView
(7)HandlerAdapter将handler执行结果ModelAndView返回给DispatcherServlet
(8)DispatcherServlet将ModelAndView传给ViewReslover视图解析器
(9)ViewReslover解析后返回具体View对象
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
(11)DispatcherServlet响应用户

SpringMVC三大组件:处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件。

处理器映射器:HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

处理器适配器:通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。

3.Spring父子容器
Spring和SpringMVC的容器具有父子关系,Spring容器为父容器,SpringMVC为子容器,子容器可以引用父容器中的Bean,而父容器不可以引用子容器中的Bean。
故:一般我们在spring.xml中不扫描@Controller(MVC)注解、在springmvc.xml中不扫描@service(AOP)和@Repository。

4 url-pattern
url-pattern的匹配顺序:
精确路径匹配 – 目录匹配(最长路径优先)-- 拓展名匹配(如*.do)-- 默认匹配(如/)

url-pattern配置为"/“和”/*"的区别:url-pattern配置/*的时候会覆盖所有Servlet,包括处理jsp的JspServlet,而/只会覆盖DefaultServlet,不会影响JspServlet。

5.SpringMVC对RESTful的支持
REST介绍:REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。

RESTful 的特性:
资源(Resources):把一个具体信息可以用一个 URI(统一资源定位符)指向它,要获取这个资源,访问它的 URI 就可以。
表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层 (Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
状态转化(State Transfer):客户端让服务器端发生“表现层状态转化” 。具体说, 就是 HTTP 协议里面,四个表示操作方式的动词:GET 、POST 、PUT 、DELETE 。

SpringMVC对RESTful的支持:
URL-PATTERN :设置为/,方便拦截RESTful 请求。
@PathVariable:可以解析出来URL中的模板变量({id})
RESTful服务中一个重要的特性就是一种资源可以有多种表现形式,在SpringMVC中可以使用ContentNegotiatingManager这个内容协商管理器来实现这种方式(不过现在RESTful响应的数据一般都是JSON格式,不需要ContentNegotiatingManager)。

6.SpringMVC与Struts2区别
最直观的就是Structs2使用注解比较少,因为它是类级别的拦截,类属性被所有方法共享,没法对方法进行很多注解标记。
Struts2:
类级别的拦截,故类属性被所有方法共享;
入口是StructsPrepareAndExcuteFilter(Structs1是ActionServlet)。–filter

八、Spring源码相关问题

持续更新。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值