SpringBoot-Spring-SpringMVC常见问题
一、Spring Boot
1、什么是Springboot
Spring Boot是Spring开源的子项目,是Spring组件一站式解决方案,简化了Spring的难度,简化了很多配置,提供了各种启动器。
2、为什么使用Springboot
独立运行,简化配置,自动配置,无代码生成和XML配置,应用监控,上手容易。
3、Springboort的核心配置文件
application和bootstrap;
application主要用于Springboot的自动化配置。
bootstrap配置文件主要用于:一些固定的不能覆盖的配置;一些加密/解密的场景;使用spring cloud config配置中心时,需要在bootstrap配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息。
4、Springboot的配置文件的格式
yml和properties
properties文件以“.”进行分隔,在yml中以“:”分隔;
yml中的格式和json有点想,是K-V格式,通过“:”赋值;
yml中缩进不要用tab,可能报错,每个K的冒号后面加空格,
使用spring cloud的maven进行构造项目,把properties改成yml后,一定要mvn clean,
yml格式不支持@PropertySource注解导入配置
5、Spingboot的核心注解
@SpringBootApplication:用在主类上,标识这是一个Spring Boot应用,用来开启SpringBoot的各项功能。它是@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan的组合,也可以用这三个注解来带起@SpringBootApplication
@ComponentScan:用来代替配置文件中的component-scan配置,开启组件扫描,自动扫描包路径下的@Component注解进行注册bena实例到context中。
@Configuration:用来代替applicationContext.xml配置文件。
@EnableAutoConfiguration:允许SpringBoot自动配置注解,开启这个注解后,SpringBoot就能根据当前类路径下的包或者类来配置Spring Bean。
6、Springboot需要容器自动运行吗?
可以不需要,springboot内置了tomcat/jetty等容器。
7、运行Springboot的方式
运行main函数;
放到容器运行;
打成jar包,使用命令运行;
使用maven或者grandle插件运行;
8、Springboot中的starters
starters会把所有用到的依赖都给包含进来,避免了开发者自己去引入依赖。
不同的starter为了解决不同的依赖,内部会有很大的差异,虽然实现起来各有差异,但是基本上都是用到ConfigurationProperties和AutoConfiguration。springboot坚信“约定大于承诺”,所以使用ConfigurationProperties来保存配置,且这些配置都有一个默认值,没有主动覆盖默认值的情况下,默认值会生效。而且ConfigurationProperties还让所有的配置属性都聚集到一个文件中,这就让我们避免了配置很多XML。
9、Springboot启动时运行特定的代码
可以实现ApplicationRunner和CommandLineRunner,实现方式一样,都只提供了一个run方法。
10、Springboot读取配置的方法
@PropertySource,@Value,@Environment,@ConfigurationProperties
11、Springboot的日志框架
java.util.Loogging ,Log4j2,logBack
12、热部署
spring loaded
spring-boot-devtools
13、springboot的配置的加载顺序
properties->yml->环境变量->命令行参数
14、多套环境配置
applcation.properties
application-dev.properties
application-test.properties
application-prod.properties
15、Springboot可以兼容老的Spring项目
使用@ImportResource注解导入老Spring的配置文件
16、保护措施
使用https,启用CSRF保护,使用内容安全策略防止xss攻击,升级到最新版本,检查依赖
17、Springboot开启事务
@EnableTransactionManagement 开始事务后,在Service使用@Transactional直接
18、使用缓存
加入依赖spring-boot-starter-cache,然后使用@EnableCaching开启缓存功能,使用@Cacheble注解
二、Spring
1、代理模式
为什么需要代理模式?
代理模式是提供了对目标对象的另外访问方式,通过代理对象访问目标对象,这样实现,可以砸目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。代理对象是目标对象的扩展,在调用时是调用代理对象,并不会调用目标对象。
讲讲静态代理模式的优点及其瓶颈?
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者继承相同的父类。
静态代理可以在不改变目标对象的前提下,对目标功能扩展。但是代理对象和目标对象需要实现一样的接口,所以会有很多代理类,同时,一旦增加了方法,代理对象和目标对象都需要维护。
对Java 接口代理模式的实现原理的理解?
代理对象的生成是利用JDK的API,利用发射,动态的在内存中构建代理对象,需要我们指定创建代理对象/目标对象实现的接口的类型。
代理对象不需要实现接口,但是目标对象一定要实现接口。
如何使用 Java 反射实现动态代理?
谈谈对Cglib 类增强动态代理的实现?
有时候目标对象只是一个单独的对象,并没有实现任何的接口,就需要使用目标对象的子类的方式实现代理,就叫做Cglib代理。也叫作子类代理。
2、Spring AOP相关问题
1、AOP的实现方式
AOP是基于动态代理的,动态代理有JDK代理和CGLib代理,
2、AOP的作用
Spring声明式事务管理配置
参数校验
实现数据库读写分离
判断权限
日志管理
信息过滤,页面转发等。
3、什么是 AOP?
AOP是面向切面编程,采用横切的技术,将设计多业务流程的通用功能抽取并单独封装,形成独立的切面,在合适的时机将这些切面横向切入到业务流程指定的位置中。让开发者单独编写功能代码,在执行过程中,Sping会根据业务流程执行横切代码。
4、point cut,advice,Join point是什么?
Advice:表示通知,是切面的具体实现方法,可以分为前置通知,后置通知,异常通知,环绕通知,最终通知。
Pointcut:表示切入点,用于定义通知应该切入到哪些连接点上,不同的通知同窗需要切入到不同的连接点上,<aop:pointcut>。
Joinpoint:表示连接点,也就是业务流程在运行过程中需要插入切面的具体位置。
5、join point 和 point cut 的区别?
joinpoint 是表示切面中可以切哪些方法;当选择了要切哪些方法,那这些方法就是Pointcut;
6、谈谈对SpringAOP Weaving(织入)的理解?
把切面应用到目标对象来创建新的代理对象的过程,有编译期织入,类装载织入,动态代理织入;
动态代理织入 是在运行的时候为目标类增加增强子类的方式。
7、谈谈SpringAOP Introduction(引入)的理解?
引入时一种特殊的增强,它为类添加一些属性和方法,即时一个类没有实现某个接口,通过introduction,可以动态的为这个类添加接口的实现逻辑,让类成为这个接口的实现类。
8、讲解OOP与AOP的简单对比?
区别:
面向目标不同:OOP是面向名词领域,AOP是面向动词领域;
思想结构不同:OOP是纵向的,AOP是横向的;
注重方面不同:OOP注重业务逻辑单元的划分,AOP偏重业务员处理过程中相同的步骤或阶段。
使用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程度的可重用性,同时提高了开发效率。
9、讲解Spring 框架中如何基于 AOP 实现的事务管理?
AOP的事务管理是声明式事务管理,其本质方法就是对方法前后进行拦截,然后在目标方法之前创建或者加入一个事务,在执行完目标方法后根据执行情况提交或者回滚事务。声明式事务不需要通过编程的方式管理事务。
有两种常用的方式,一种是基于xml配置文件,另一种是基于@Transacyional注解。
3、Spring IOC相关问题
1、什么是 IOC?
IOC就是控制反转,是一种设计思想,IOC意味着将你的对象交给Spring IOC容器管理,而不是在自己的对象内部自己控制。是IOC控制对象,控制外部资源获取。依赖对象的获取被反转了。
对象和对象之间是低耦合,方便测试,利于功能复用,整个体系结构变得灵活。
2、Spring 中有多少种 IOC 容器?
Spring提供了两种类型的IOC容器:BeanFactory,ApplicationContext
BeanFactory:IOC的基本实现;ApplicationContext提供了更多高级特性,是BeanFactory的子接口;
BeanFactory面向的是Sping本身,ApplicationContext是面向开发者,几乎所有的应用场合都是直接使用ApplicationContext;在IOC容器读取Bean配置创建Bean实例之前,必须要先对容器实例化。
ClassPathXmlApplicationContext:从 类路径下加载配置文件;
FileSystemXmlApplicationContext: 从文件系统中加载配置文件;
ConfigurableApplicationContext 扩展于 ApplicationContext,新增加两个主要方法:refresh() 和 close(), 让ApplicationContext 具有启动、刷新和关闭上下文的能力;
ApplicationContext 在初始化上下文时就实例化所有单例的 Bean;
WebApplicationContext 是专门为 WEB 应用而准备的,它允许从相对于 WEB 根目录的路径中完成初始化工作;
3、怎么避免循环依赖?
最好的处理方法是重新设计代码。当然也有不就办法:
改用setter注入方式,setter是按需注入的,允许依赖对象为null;
@Lazy注解,延迟初始化
4、说说对Spring IOC 的单例模式和高级特性?
在大部分情况下,容器中的大部分bean是singleton类型的,当以单一bean需要和另外一个单例bean写作时,或者一个单例bean要引用另外一个非单例bean时,通常情况下将一个bean定义为另外一个bean的属性值就行了。不过对于具有不同生命周期的bean来说,这样就有问题了。
Lookup方法注入:Lookup具有容器覆盖受容器管理的bean方法的能力,从而返回指定名字的bean实例。
5、BeanFactory 和 FactoryBean 有什么区别?
BeanFactory是Spring中比较原始的Factory,ApplicationContext接口是由BeanFactory接口派生来的。
BeanFactory是接口,提供了IOC容器最基本的形式,给具体的IOC容器提供了规范。
FactoryBean也是接口,为IOC容器中的Bean的实现提供了更加灵活的方式,FactoryBean在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式。在默写情况下,实例Bean过程比较复杂,如果按照传统的方式,则需要配置大量的信息,配置方式的灵活性有限。Spring为此提供了一个BeanFactory的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。
6、谈谈Spring Bean 创建过程中的设计模式?
简单工厂模式:BeanFactory
工厂模式:FactoryBean接口
单例模式:Spring依赖注入Bean实例默认是单例的。
适配器模式:SpringMVC中的适配器HandlerAdapter,HandlerAdapter根据Handler规则执行不同的Handler。
装饰器模式:Sping中用到包装器模式的类名有两种表现:一种是类名含有Wrapper,另一种是类名含有Decorator。动态个给一个对象添加一些额外的职责。
代理模式:AOP底层。
观察者模式:Spring的事件驱动模型使用观察者模式,用的地方是listener的实现。
策略模式:Spring框架的资源访问Resource接口。
模板方法模式:父类定义了骨架(调用哪些方法及顺序),某些特定方法由子类实现。
7、Spring Bean的作用域
在Sping中bean默认都是单例的;
Spring的作用域有五类:
singleton:在容器中只存在一个Bean实例,是默认值。
prototype:每次从容器中调用Bean时,都会返回一个新的实例,相当于执行new xxxBean();
request:每次请求都会创建一个新的Bean;
session:同一个Http Session共享一个Bean,每次会话共享一个Bean;
globalSession:整个web应用中共享一个Bean;
4、事务相关问题
1、Transactional 注解是否可以加在 private、protected 方法上?
不可以,这个是由Spring AOP的本质决定,Transactional使用到了代理模式,CGLIB代理时,如果方法是protected、private或者默认可见性时,动态代理时,将会出现问题,所以在protected、private 或者默认可见性的方法上使用 @Transactional 注解,将被忽略,也不会抛出任何异常。
2、事务的传播属性
PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,
3、为什么抛出了异常,事务却没有回滚?
Spring的事务机制中,more的事务只有发射了未被捕获的RuntimeException时才会回滚。另外在service中有try,catch代码块,且其中有多个方法时,当后一个方法抛出异常时前一个方法中执行的也不会回滚,这里需要在catch中处理完逻辑后,手动抛出一个RuntimeException,这样前一个方法中执行的逻辑才会回滚。
4、Spring 事务是如何保证线程安全的?
线程安全问题都是由全局变量和静态变量引起的。
一种方式是使用ThreadLocal保存各自线程的数据。
三、SpringMVC
SpringMVC原理:
1、用户发起请求到前端控制器(DispatcherServlet)
2、前端控制器请求处理器映射器(HandlerMappering)去查找处理器(Handle):通过xml配置或者注解进行查找
3、找到以后处理器映射器(HandlerMappering)像前端控制器返回执行链(HandlerExecutionChain)
4、前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)去执行处理器(Handler)
5、处理器适配器去执行Handler
6、Handler执行完给处理器适配器返回ModelAndView
7、处理器适配器向前端控制器返回ModelAndView
8、前端控制器请求视图解析器(ViewResolver)去进行视图解析
9、视图解析器像前端控制器返回View
10、前端控制器对视图进行渲染
11、前端控制器向用户响应结果