likes
comments
collection
share

Spring面试题

作者站长头像
站长
· 阅读数 17

1. Spring 用到了哪些设计模式

简单工厂模式:BeanFactory就是简单工厂模式的体现

工厂方法模式:FactoryBean就是典型的工厂方法模式。spring在使用getBean()调用获得该bean时,会自动调用该bean的getObject()方法。每个 Bean 都会对应一个 FactoryBean,如 SqlSessionFactory 对应 SqlSessionFactoryBean。

单例模式:一个类仅有一个实例,提供一个访问它的全局访问点。Spring 创建 Bean 实例默认是单例的。

适配器模式:SpringMVC中的适配器HandlerAdatper。由于应用会有多个Controller实现,如果需要直接调用Controller方法,那么需要先判断是由哪一个Controller处理请求,然后调用相应的方法。当增加新的 Controller,需要修改原来的逻辑,违反了开闭原则(对修改关闭,对扩展开放)。 为此,Spring提供了一个适配器接口,每一种 Controller 对应一种 HandlerAdapter 实现类,当请求过来,SpringMVC会调用getHandler()获取相应的Controller,然后获取该Controller对应的 HandlerAdapter,最后调用HandlerAdapter的handle()方法处理请求,实际上调用的是Controller的handleRequest()。每次添加新的 Controller 时,只需要增加一个适配器类就可以,无需修改原有的逻辑。

常用的处理器适配器:SimpleControllerHandlerAdapter,HttpRequestHandlerAdapter,AnnotationMethodHandlerAdapter。

代理模式:spring 的 aop 使用了动态代理,有两种方式JdkDynamicAopProxy和Cglib2AopProxy。

观察者模式:spring 中 observer 模式常用的地方是 listener 的实现,如ApplicationListener。

模板模式: Spring 中 jdbcTemplate、hibernateTemplate 等,就使用到了模板模式

2. IOC容器初始化过程

从XML中读取配置文件。将bean标签解析成 BeanDefinition,如解析 property 元素, 并注入到 BeanDefinition 实例中。将 BeanDefinition 注册到容器 BeanDefinitionMap 中。BeanFactory 根据 BeanDefinition 的定义信息创建实例化和初始化 bean。单例bean的初始化以及依赖注入一般都在容器初始化阶段进行,只有懒加载(lazy-init为true)的单例bean是在应用第一次调用getBean()时进行初始化和依赖注入。// AbstractApplicationContext // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); 多例bean 在容器启动时不实例化,即使设置 lazy-init 为 false 也没用,只有调用了getBean()才进行实例化。loadBeanDefinitions采用了模板模式,具体加载 BeanDefinition 的逻辑由各个子类完成。#

3. Bean的生命周期

1.调用bean的构造方法创建Bean 2.通过反射调用setter方法进行属性的依赖注入 3.如果Bean实现了BeanNameAware接口,Spring将调用setBeanName(),设置 Bean的name(xml文件中bean标签的id) 4.如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()把bean factory设置给Bean 5.如果存在BeanPostProcessor,Spring将调用它们的postProcessBeforeInitialization(预初始化)方法,在Bean初始化前对其进行处理 6.如果Bean实现了InitializingBean接口,Spring将调用它的afterPropertiesSet方法,然后调用xml定义的 init-method 方法,两个方法作用类似,都是在初始化 bean 的时候执行 7.如果存在BeanPostProcessor,Spring将调用它们的postProcessAfterInitialization(后初始化)方法,在Bean初始化后对其进行处理 8.Bean初始化完成,供应用使用,这里分两种情况: 8.1 如果Bean为单例的话,那么容器会返回Bean给用户,并存入缓存池。如果Bean实现了DisposableBean接口,Spring将调用它的destory方法,然后调用在xml中定义的 destory-method方法,这两个方法作用类似,都是在Bean实例销毁前执行。 8.2 如果Bean是多例的话,容器将Bean返回给用户,剩下的生命周期由用户控制。

4. BeanFactory和FactoryBean的区别?

BeanFactory:管理Bean的容器,Spring中生成的Bean都是由这个接口的实现来管理的。

FactoryBean:通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,直接用xml配置比较麻烦,这时可以考虑用FactoryBean,可以隐藏实例化复杂Bean的细节。当配置文件中bean标签的class属性配置的实现类是FactoryBean时,通过 getBean()方法返回的不是FactoryBean本身,而是调用FactoryBean#getObject()方法所返回的对象,相当于FactoryBean#getObject()代理了getBean()方法。如果想得到FactoryBean必须使用 '&' + beanName 的方式获取。

Mybatis 提供了 SqlSessionFactoryBean,可以简化 SqlSessionFactory的配置:

5. Bean注入容器有哪些方式?

1、@Configuration + @Bean

@ComponentScan放置在我们的配置类上,然后可以指定一个路径,进行扫描带有特定注解的bean,然后加至容器中。特定注解包括@Controller、@Service、@Repository、@Component

@Import注解导入

实现BeanDefinitionRegistryPostProcessor进行后置处理。

使用FactoryBean接口

6. Spring自动装配的方式有哪些?

byType(根据类型),byName(根据名称)、constructor(根据构造函数)。

Spring怎么解决循环依赖的问题?

首先,有两种Bean注入的方式。构造器注入和属性注入。对于构造器注入的循环依赖,Spring处理不了,会直接抛出BeanCurrentlylnCreationException异常。 对于属性注入的循环依赖(单例模式下),是通过三级缓存处理来循环依赖的。而非单例对象的循环依赖,则无法处理。 下面分析单例模式下属性注入的循环依赖是怎么处理的: 首先,Spring单例对象的初始化大略分为三步: createBeanInstance:实例化bean,使用构造方法创建对象,为对象分配内存。 populateBean:进行依赖注入。 initializeBean:初始化bean。 Spring为了解决单例的循环依赖问题, 使用了三级缓存: singletonObjects:完成了初始化的单例对象map,bean name --> bean instanceearlySingletonObjects :完成实例化未初始化的单例对象map,bean name --> bean instancesingletonFactories : 单例对象工厂map,bean name --> ObjectFactory, 单例对象实例化完成之后会加入singletonFactories。在调用createBeanInstance进行实例化之后, 会调用addSingletonFactory,将单例对象放到singletonFactories中。

假如A依赖了B的实例对象,同时B也依赖A的实例对象。A首先完成了实例化,并且将自己添加到singletonFactories中接着进行依赖注入, 发现自己依赖对象B,此时就尝试去get(B)发现B还没有被实例化,对B进行实例化然后B在初始化的时候发现自己依赖了对象A,于是尝试get(A),尝试一级缓存singletonObjects和二级缓存earlySingletonObjects没找到,尝试三级缓存singletonFactories,由于A初始化时将自己添加到了singletonFactories,所以B可以拿到A对象,然后将A从三级缓存中移到二级缓存中B拿到A对象后顺利完成了初始化,然后将自己放入到一级缓存singletonObjects中此时返回A中,A此时能拿到B的对象顺利完成自己的初始化由此看出,属性注入的循环依赖主要是通过将实例化完成的bean添加到singletonFactories来实现的。而使用构造器依赖注入的bean在实例化的时候会进行依赖注入,不会被添加到singletonFactories中。比如A和B都是通过构造器依赖注入,A在调用构造器进行实例化的时候,发现自己依赖B,B没有被实例化,就会对B进行实例化,此时A未实例化完成,不会被添加到singtonFactories。而B依赖于A,B会去三级缓存寻找A对象,发现不存在,于是又会实例化A,A实例化了两次,从而导致抛异常。

总结:1、利用缓存识别已经遍历过的节点; 2、利用Java引用,先提前设置对象地址,后完善对象。

Springboot的优点

内置servlet容器,不需要在服务器部署 tomcat。只需要将项目打成 jar 包,使用 java -jar xxx.jar一键式启动项目 SpringBoot提供了starter,把常用库聚合在一起,简化复杂的环境配置,快速搭建spring应用环境可以快速创建独立运行的spring项目,集成主流框架

7.Spring Boot 的核心注解是哪个

启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解, 主要组合包含了以下 3 个注解:@SpringBootConfiguration:组合了

@Configuration注解,实现配置文件的功能。

@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。

@ComponentScan:Spring组件扫描。

8. 自动配置原理

EnableAutoConfiguration主要由 @AutoConfigurationPackage,@Import(EnableAutoConfigurationImportSelector.class)这两个注解组成的。

@Import 将EnableAutoConfigurationImportSelector注入到spring容器中,EnableAutoConfigurationImportSelector通过SpringFactoriesLoader从类路径下去读取META-INF/spring.factories文件信息,此文件中有一个key为org.springframework.boot.autoconfigure.EnableAutoConfiguration,定义了一组需要自动配置的bean。

9. Spring Boot 打成的 jar 和普通的 jar 有什么区别 ?

Spring Boot 项目最终打包成的 jar 是可执行 jar ,这种 jar 可以直接通过 java -jar xxx.jar 命令来运行,这种 jar 不可以作为普通的 jar 被其他项目依赖,即使依赖了也无法使用其中的类。Spring Boot 的 jar 无法被其他项目依赖,主要还是他和普通 jar 的结构不同。普通的 jar 包,解压后直接就是包名,包里就是我们的代码,而 Spring Boot 打包成的可执行 jar 解压后,在 \BOOT-INF\classes 目录下才是我们的代码,因此无法被直接引用。如果非要引用,可以在 pom.xml 文件中增加配置,将 Spring Boot 项目打包成两个 jar ,一个可执行,一个可引用。

10. springcloud介绍

Spring Cloud Eureka实现微服务架构中的服务治理功能, 服务治理是微服务架构中最为核心和基础的模块。

Spring Cloud Ribbon 是基于HTTP和TCP的客户端负载均衡工具,基于Netflix Ribbon实现。Spring Cloud Ribbon 会将REST请求转换为客户端负载均衡的服务调用。 开启客户端负载均衡调用: 服务提供者启动多个服务实例注册到服务注册中心; 服务消费者直接通过调用被@LoadBalanced 注解修饰过的RestTemplate 来实现面向服务的接口调用。

Spring Cloud Hystrix Hystrix具备服务降级、服务熔断、线程隔离、请求缓存、请求合并及服务监控等强大功能。

Spring Cloud Feign 基于Netflix Feign 实现,整合了Spring Cloud Ribbon 与Spring Cloud Hystrix, 它提供了一种声明式服务调用的方式。

Spring Cloud Zuul API网关,为微服务架构中的服务提供了统一的访问入口,客户端通过API网关访问相关服务。所有客户端的访问都通过它来进行路由及过滤。它实现了请求路由、负载均衡、校验过滤、服务容错、服务聚合等功能。

Spring Cloud Config Spring Cloud Config分为服务端和客户端。服务端也称为分布式配置中心,

Spring Cloud Bus

Spring Cloud Security Spring Cloud Security 为构建安全的SpringBoot应用提供了一系列解决方案,结合Oauth2可以实现单点登录、令牌中继、令牌交换等功能。

转载自:https://juejin.cn/post/7292994406344015926
评论
请登录