每天五道面试题!只记录答案,不标出源码,有什么不对的地方欢迎评论,共同进步。
1. Spring框架用到的设计模式
1、工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例。
2、单例模式:Bean默认为单例模式。
3、代理模式:Spring AOP功能用到了JDK动态代理和CGLIB字节码生成技术。
4、模板方法:用来解决代码重复问题。比如:RestTemplate、JmsTemplate、JpaTemplate。
5、观察者模式:定义了对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,比如Spring中listener的实现–ApplicationListener。
2. Spring的一级缓存为什么解决不了循环依赖问题?
对象的创建过程分为实例化过程和初始化过程,实例化指的是在堆中分配内存空间,初始化指的是给成员变量赋值(构造方法或者setter方法赋值,缓存机制下可以解决setter的循环依赖,但是不能解决构造方法的循环依赖,需要加@Lazy
注解,所以一般都会给一个类加空的构造函数)。
只完成实例化但是未初始化的对象称为非完全状态对象,完成实例化和初始化的对象称为完全状态对象。
如果只有一级缓存 ,那么非完全状态对象和完全状态对象都是放在一级缓存中,那么取的时候可能会取到非完全对象,就可能出现空指针异常。
3. Spring除了二级缓存,为什么需要三级缓存?
我们需要三级缓存的最主要意义就是所需要的类可能是简单对象,也可能是需要代理的对象,当我们向三级缓存中放置匿名内部类的时候,可以在获取时决定到底是简单对象,还是代理对象。保证了获取到的bean唯一。
循环依赖时,假如我们需要创建A对象,而A、B循环依赖。我们创建A的时候需要B,就会创建B,B又需要A,那么三级缓存会创建未完成状态对象A放入到二级缓存中(我理解应该是检测到A正在创建过程中,而此时走的路径跟正式创建时走的是不一样的),这样可以让B先拿到个未完成的凑合一下,变成完成的,完成的B会放到一级缓存中,这时候我们在创建A的时候就会从一级缓存中拿到B,之后执行初始化过程,从三级缓存的getEarlyBeanReference(beanName, mbd, bean)
走一遍,如果A需要代理,就会产生一个完全的A,放入到一级缓存后,会删除二级三级缓存中的A。
为什么不第一次创建A就直接创建个代理的呢?B站有老师讲的原因是只有在需要的时候才会进行代理,我们第一次创建一个未完成的A只是来解决循环依赖问题。
4. Spring Boot的优势
1、独立运行:Spring Boot内嵌了各种servlet容器,例如Tomcat、Jetty等,现在不再需要打成war包部署到容器中,Spring Boot只要打成一个可执行的jar包就能独立运行,所有的依赖都在一个jar包内。
2、简化配置:spring-boot-starter-web启动器自动依赖其他组件,简少了maven的配置。
3、自动配置:Spring Boot能根据当前类路径下的类、jar包来自动配置bean,如添加一个spring-boot-starter-web启动器就能拥有web的功能,无需其他配置。
4、无代码生成和XML配置:Spring Boot配置过程中无代码生成,也无需XML配置文件就能完成所有配置工作,这一切都是借助于条件注解完成的,这也是Spring4.x的核心功能之一。
5、应用监控:Spring Boot提供一系列端点可以监控服务及应用,做健康检测。
5. Spring Boot的核心注解
核心注解就是一个:@SpringBootApplication
,主要包含以下三个注解:
1、@SpringBootConfiguration
:组合了@Configuration注解,实现了配置文件的功能。
2、@EnableAutoConfiguration
:开启自动配置的功能,也可以关闭某个自动配置的选项。
3、@ComponentScan
:Spring组件扫描。