想到—你对spring理解的面试题
spring 呢 是由java语言开发得一个框架
这个框架得主要作用呢 是方便开发者更便捷得开发程序、它主要封装了java类的反射、以及容器启动后类互相之间调用问题
熟悉 spring得都了解 spring 有两个主要特性 IOC AOP
简单描述spring呢 也就这两个
控制反转和依赖注入
面向切面
控制反转 是解决类的统一反射
主要作用是将java原生类 由spring框架反射这个类的信息 在容器初始化后调用
依赖注入 是解决各个类之间互相调用问题、类解耦
面向切面
使用动态代理来代理业务逻辑代码的执行 在执行代理层的时候 可以在方法中织入我们想要执行的方法
那么复杂点想想呢
复杂点结合容器启动过程、对比所有的你碰到得编程系统、比如linux、win系统启动过程、还有tomcat启动
linux : 读取配置文件、加载配置文件、加载系统执行文件、请求内存、加载完毕、刷新上下文
tomcat : 读取配置文件、加载配置文件、加载应用jar、加载完毕、刷新上下文
win : 读取配置文件、加载配置文件、服务注册到注册表、注册表启动必须程序、启动完毕
【像什么启动端口、就不谈了、了解程序启动步骤、想的还是有点浅、待完善】
1、寻找配置文件、加载配置【这跟是系统上的设置一样、读取用户设置你再开机】
2、读取到配置文件、接下来启动jdk、这里就不讲、也将不明白
3、spring要读取 我们写的java类文件、将其反射到内存中、用来调用
4、启动完成检查启动项是否都已将ok、刷新上下文
第二部呢 涉及到jdk以及c之间的启动、
这里可以大概猜想下、
spring启动-本身也是java文件、jdk编译spring文件、那么要编译spring文件按照java中得双亲委派机制要编写父类
当然所有的父类都会刀jdk中、那么也就是说先编译jdk、
jdk启动后、启动spring基类包文件、spring编译完成、读取配置文件、去编译我们得应用jar、我们的应用jar又会有基类包文件、
转向再去编写基类【也就是应用上的依赖包和父类包】
当应用jar编译完成后、进入反射分配内存阶段
统计所有java类信息、需要内存信息、分配内存、把各个类得对象信息放到方法区【1.8里叫 元数据区 也好理解、所有class得计算机内存区、在请求之后是数据运行区就】
上边呢把整个应用得编译、分配内存、大概才想了一下
那么程序事怎么运行的呢?
也可以猜想下
一堆内存数据、访问该到哪里接入?
为什么就到spring controller里了呢?
我可以做这样一个设想
我有一块专门的请求处理区。
这里呢 我放一个匹配器、所有的请求来了都到这、把url一截断处理 我们能得到不同的字符
这个字符呢 也就对应着 不用controller=的url
然后根据这个字符找到不同的方法区对应的方法地址
就可以往下的内存中链形行走了
** 有一个特别有意思的事情
spring容器启动过程中、类循环调用
两个基类包调用了同一个类、在容器启动时候导致类循环调用启动失败
把上边类启动过程搞明白了、一琢磨就想到哪里出问题了、类启动初始化bean的过程中、有bean初始化一半的时候、碰到了另一个类对他同时也进行初始化
【至于为什么会这样、在类的初始化过程中、也是分类好几步、毕竟一个类的初始化不能一步到位、就在这个初始化中】
问题就到了类初始化问题
那么类的初始化、刨除双亲委派机制 父类初始化完毕才能初始化子类
剩下就是 类初始化 要初始化引用注入java类
类循环调用就在这里出现了、a类初始化、需要初始化b、b类初始化需要初始化c、c类初始化需要初始化a、
解决办法:lazy load
当然这样的引用常出现在糅合配置类上、如果配置清晰、也不会有这样的问题