每日十道面试题(三)
1. 讲一下spring的ioc的理解?
ioc又叫做控制反转,我们不再需要手动的去实例化对象,而是把我们设计好的bean交给ioc容器去控制,依赖注入就是很好的实现了控制反转,不再自己去获取资源**,ioc控制了外部资源的获取包括对象资源和常量数据那些都可以从容器获取**,有点像代理模式,我们把类A交给spring,spring管理所有对象,你怎么创建我并不关心,但是我要用对象的时候,只需要spring提供即可,在以前我们是需要的时候就自己马上实例创造一个然后用,太麻烦了
2. springmvc的执行流程?
- 所有前端的url地址映射进来都是先找DispatcherServlet,它是控制器负责请求分发
- 然后第二步HandlerMapping 处理器映射器**(中间商)**
- 根据url找Handler
- 将解析后的信息传递回控制器
- 控制器将信息给处理器适配器(HandlerAdapter)
- 它决定适配到对应的处理器Controller
- 然后Controller将执行完返回的具体结果给适配器,比如返回的Model
- 然后将返回的逻辑视图名,或者结果传回控制器
- 如果是逻辑视图名,就去调用ViewRESolver视图解析它的视图信息
- 将解析的视图信息返回给控制器
- 根据视图信息调用具体的视图模板
- 展现视图模板到前端
3. mybatis执行流程?原理
-
首先是Resource读取全局配置文件,
-
然后就实例化SqlSessionFactoryBuilder构造器,抽象工厂模式,专门制造SqlSessionFactory,制造完就销毁了
-
然后XMLConfigBuilder专门读取xml配置文件信息
-
Configuration来配置读取的xml信息,比较重要的是命名空间+方法名
-
配置完就可以SqlSessionFactory实例化,全局存在,比如一级缓存,提供后续便利
-
transactional事务管理,控制着事务
-
创建Executor,含有数据源信息
-
创建SqlSession,里面包含了mapper的接口信息
-
实现CRUD,失败就回滚,否则提交事务关闭SqlSession等
4. 说说对jdk1.7hashmap的理解和1.8的区别?
-
jdk1.7hashmap最拿手的就是数据结构是数组加链表,散列表形式,jdk1.8hashmap是数组加链表加红黑树,主要是优化扩容死锁问题,死锁在并发情况,指针地址改变就会发生
-
1.7的hashmap一上来就初始化16大小的空间,1.8只初始化加载因子都是0.75,但是只有putval时才会初始化16大小空间,有点类似懒加载
-
他们插入值都是先利用hash算出数组下标,然后再循环判断链表上是否有重复值,有就替换返回原来的值,没有就头插法然后插入在头部,然后头部在数组上
-
查找方法的话,和put一样,找不到返回null,找得到就返回对应的key
-
1.7hashMap利用hash高16位和低16位进行与运算,这是为了保证散列性,不会太容易哈希碰撞,然后再利用算出的二次哈希值与table长度-1进行与运算,这是为了保证低位都是二次哈希值的低位,这样对应数组下标很准确,这里就延申一个问题为什么数组长度都是幂等性,即使你初始化17也算作32,因为保证了幂等性之后length-1才能保证低位是1,与运算找下标的步骤更准确,而且增加了散列性
-
1.8的红黑树是当链表长度超过了7之后会自动变成红黑树结构,当缩容为6的时候又会转为链表,比较链表在长度短的时候效率比树快,数据多的时候只是怕形成单链表所以采用红黑树而不用其它树
5. 常用的几种垃圾回收算法?之间的区别
引用计数法,实际上是通过在对象头中分配一个空间来保存该对象被引用的次数,但是在环形数据循环引用的时候,那么引用计数根本不会缩减,所以会造成内存泄漏,需要进行可达性分析判断是否为垃圾
复制算法:常用于新生区,适合那种存活率低的地方,因为每次复制如果数据太大,实在太费时费力,每次复制都是一次全量检查
标记清除算法: (两次扫描)适合存活率大(老年区)内存碎片少的时候用,第一遍扫描标记我们
需要用到或者正在用的对象,第二遍然后清理其它的内存也就是没标记的地方,但这样清除容易造成坑坑洼洼,不连续的内存,有内存碎片,耗内存
标记清除整理:它实际上就是在标记清除的基础上然后再扫描整理一遍排序,然后统一清理掉后面的不需要的垃圾,这样可以形成连续的内存,所以内存碎片大的时候可以整理一下,
其实没有最好的垃圾回收算法,我们目前最优是分代收集算法,用在合适的场景
6. 类加载的流程
**加载:**javac编译的class字节码文件由类加载器读取二进制数据,在方法区创建一个Class的模板对象
链接:
- 验证:验证类是否合法,语言是否规范(双亲委派机制,沙箱安全机制)
- 准备:为类的静态成员方法区中分配内存,并设置默认初始值
- 解析:将符号引用解析为直接引用
**初始化:**已经分配了内存,所以staic变量初始化,常量初始化,构造执行等
7. 说说都知道哪些异常?如何避免或者解决
OOM:堆内存不足,可以尝试调大堆内存 xms ,但实际问题需要打印内存信息,如果是死锁,那么再调大也无济于事
StatckOverFlow:栈内存不足,解决问题同上Xss调优,
并发修改异常: 每次进行操作集合的时候有个modcount会计算修改次数,然后iterator中会有个变量存值,然后如果没有用iterator的remove方法的话就会导致modCount次数修改但是没有存,导致iterator的modCount和集合的不一致就会抛出这个方法,一定要使用iterator来修改集合元素
等
8. 谈一谈springboot如何自动装配的吧
这里用个图展示,码字比较多
文档:Springboot之Run方法解析.mindmap
链接:http://note.youdao.com/noteshare?id=c981f1d31d87cae4fab36287b1b66651
9. spring bean的生命周期
实例化 -> 属性赋值 -> 初始化 -> 销毁
-
设置bean的Aware
-
BeanPostProcessor.postProcessBeforeInitialization(Object bean, String beanName)
-
InitializingBean.afterPorpertiesSet
-
BeanPostProcessor.postProcessAfterInitialization(Object bean, String beanName)
-
SmartInitializingSingleton.afterSingletonsInstantiated
-
SmartLifecycle.start
-
bean已经在spring容器的管理下,可以做我们想做的事
-
SmartLifecycle.stop(Runnable callback)
-
DisposableBean.destroy()
10. springCloud的生态简述一下重要的几个组件的用处?
Zuul:路由网关,有效的安全隐藏了其它服务,保证了安全性,访问过滤
Eureka service:注册中心,里面有一个注册表,保存了各个服务所在的机器和端口号、Eurake Client:负责将这个服务的信息注册到Eureka Server中
Feign:@FeignClient声明式事务,注解结合restful风格,基于 Hystrix 和 Ribbon 声明式服务调用组件
ribbion:客户端负载均衡服务调用组件
**Config:**配置管理工具,支持 git 存储配置实现应用外部配置化,支持远程客户端读取配置并根据初始化参数启动项目
基于 Hystrix 和 Ribbon 声明式服务调用组件
ribbion:客户端负载均衡服务调用组件
**Config:**配置管理工具,支持 git 存储配置实现应用外部配置化,支持远程客户端读取配置并根据初始化参数启动项目