手把手教你锤面试官 03——Spring 怎么那么简单
本文是手把手教你锤面试官系列第三篇文章,该系列主要为大家分析和讲解在面试过程中,遇到面试官经常提出的面试问题如何进行攻防。另外本系列的文章也会提供许多小技巧给大家去间接试探出面试官的技术能力和专业水平,从而达到碾压面试官的目的。本系列文章只适用于JAVA工程师。
在JAVAEE的世界里面Spring基本上无所不能,无处不在,基本上除了生孩子以外,可以满足JAVA工程师的全套开发需要。Spring全家桶有多强大,可以在https://spring.io/上面看看。常用的全家桶在下图这张百度来的图片上面可以看出,但其实spring还有一些别的比较冷门的工具,如spring http invoker(微服务未流行的时候的分布式通信框架)、springJdbc、SpringData等,Spring还可以整合各种冷门或热门的MVC或者ORM等框架,如struts、Mybatis、Hibernate、 JNA、Quartz等....基本上只有你想不到,没有它整不了的。所以spring框架是绕不过去的一个面试必考点,本文我将结合自己多年工作经验给大家梳理一下在面试过程中关于spring框架的问题以及回答。
注意:
1.本文只讨论spring框架的相关知识,Springmvc,Springboot,SpringCloud等Spring衍生框架不在本文的讨论范围;
2.本文很多的解答是根据本人工作经验总结的个人理解,不一定全对,如有发现错误欢迎留言指正;
3.强烈建议大家花点时间去阅读Spring的源代码,本人2017年的时候花了差不多两个月的时间根据网上的教程看完了从githup上下载下来的spring3.0的源代码,受益无穷,不一定需要吃透,只要大概的看一下你就会对设计模式有了质的领悟。
面试官对于spring的问题主要有以下几个:
0.spring是什么东西,干什么用的?
1.spring的核心IOC和AOP是用来干嘛的?怎么实现的?
2.spring加载Bean的启动机制和顺序是怎样的?
3.Spring的3个核心组件是哪些,分别用来干啥用的?
4.谈一下在Spring中托管的bean的作用域和生命周期是怎样的?
5.Spring中的事务传播和隔离级别有哪些?
0.0回答
spring与其说是一个框架不如说是一个容器,表面上看是用来协助程序员管理Bean。但实际上我个人认为,Spring这个容器专门内置了一系列的组件和工具来规范设计模式学得不好的程序员简单方便的使用各种设计模式写出高质量的代码。大家可以回忆一下,我们使用Spring之后有一个关键字是不是很少见了——new,基本上你用Spring管理Bean之后,new是不是消失了(想想ApplicationContext的使用)?还有代码的复用性是不是提高了(想想Service的使用)?很多在实例化的时候需要进行条件判断进行实例化的判断是不是也少了?Spring本身就是一套集合了工厂模式、单例模式、原型模式、代理模式合观察者模式一体的优秀框架。所以我们可以说,spring是一个对bean进行托管的容器或者手脚架,作用是给设计模式学得不好的程序员提供一套标准和组件,让他们可以写出更规范标准优质的代码。
1.1回答
我们常说Spring的核心就是两个——IOC(反转控制)和AOP(面向切面编程)。
IOC的功能用人话来说就是,我们可以不用通过new就可以拿到一个Bean的对象(结合我上一篇文章中对涉及模式的梳理来理解)。
spring的IOC实现原理非常简单,就是通过解析注解或者xml中的配置拿到这个类的描述信息,通过JAVA的反射机制实现不用new直接将一个object对象转化成目标Bean对象。我们弄清楚IOC的实现就是反射之后可以结合dom4j非常简单的自己动手写一个IOC框架,快的话不需要20分钟。大概思路如下:启动主类调用dom4j去解析某个xml里面对class的包描述,然后通过反射机制Class.forName等方法就可以实例化出来一个对象啦。
AOP,就是所谓的面向切片编程。用人话来说就是我可以在某个class字节码文件中的某个方法的前面或者后面,在该方法执行的时候插入一段执行代码。专业的术语描述如下:将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理。
Spring的AOP实现原理非常简单,比IOC还要简单很多。AOP是基于代理模式(又是设计模式)实现的,它分为静态代理和动态代理。
静态代理,就是把一个通过AspectJ组件在把AOP切面中方法所在的JAVA文件编译成class的时候,会把切入的方法添加到该java文件中后再去编译class。
动态代理,就是JAVA文件编译成class之后,动态去修改class里面切面方法的所在类的内容。
Spring的动态代理由两种实现方式:
1)通过JDK的动态代理既利用接口和反射机制去动态改变一个class中的内容。
2)利用cglib-xxx.jar包中Enhancer工具类,通过追溯目标类父类的方式,通过回调机制去动态修改class中的内容。(该段描述可能存疑,可能不是修改,而是另外创建了一个class。时间太长有可能记错了,也没找到相关资料)
2.2回答
spring的启动机制和顺序
看下面三张这张百度来的图片就可以说清楚大概了
1)简单版
2)通用版
3)逼格版(主要是Spring生成Bean对象的机制和流程)
3.3回答
spring的3个核心组件如下
Spring Core:核心类库,提供IOC服务
Spring Context:提供框架式的Bean访问方式(如BeanFactory,ApplicationContext),以及企业级功能(JNDI、Corn定时任务等);
Spring AOP:AOP服务,调用cglib.jar
4.4回答
Bean的生命周期如下
Bean的作用域如下
Spring IOC容器创建一个Bean实例时,可以为Bean指定实例的作用域,作用域包括singleton(单例模式)、prototype(原型模式)、request(HTTP请求)、session(会话)、global-session(全局会话)。singleton是默认的。
5.5回答
事务传播(@Transactional注解中配置,如@Transactional(propagation=Propagation.REQUIRED))
① PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的默认设置。
② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
④ PROPAGATIONREQUIRESNEW:创建新事务,无论当前存不存在事务,都创建新事务。
⑤ PROPAGATIONNOTSUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行
隔离级别(Transactional注解中配置,如@Transactional(isolation = Isolation.SERIALIZABLE))
① ISOLATION_DEFAULT:这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。
② ISOLATIONREADUNCOMMITTED:读未提交,允许另外一个事务可以看到这个事务未提交的数据。
③ ISOLATIONREADCOMMITTED:读已提交,保证一个事务修改的数据提交后才能被另一事务读取,而且能看到该事务对已有记录的更新。
④ ISOLATIONREPEATABLEREAD:可重复读,保证一个事务修改的数据提交后才能被另一事务读取,但是不能看到该事务对已有记录的更新。
⑤ ISOLATION_SERIALIZABLE:一个事务在执行的过程中完全看不到其他事务对数据库所做的更新。
结束语:
好累,Spring不愧是企业级JAVA的核心,本来想浓缩几个段落就写完的,没想到越写越多一发不可收拾。又到了传授大家小技巧的时候了。想看看一个面试官的Spring能力如何,可以问他一个问题——都说spring的两大核心是IOC和AOP,为什么依赖注入(DI)不是Spring的核心之一呢?不管面试官怎么东拉西扯,解释DI为什么不是spring的核心都可以判断他的水平非常低。因为答案很简单——DI就是IOC,只是叫法不同而已。就像散户和韭菜一样,都是指同一个东西。
下一篇文章我们讲讲轻松简单的话题——面试中怎么去应付redis的相关提问。
评论