Spring是什么
- Spring是一个轻量级、非侵入式、一站式、模块化的Java EE开发框架,其目的是用于简化企业级应用程序开发。
- Spring框架的核心功能可以应用在任何Java应用程序中,对Java EE平台上的Web应用程序有更好的扩展性。
Spring的优点
- 轻量级:Spring在大小和透明性方面绝对属于轻量级的,基础版本的Spring框架大约只有2MB。
- 控制反转(IOC):Spring使用控制反转技术实现了松耦合。依赖被注入到对象,而不是创建或寻找依赖对象。
- 容器:Spring包含并管理应用程序对象的配置及生命周期。
- MVC框架:Spring的web框架是一个设计优良的web MVC框架,很好的取代了一些web框架。
- 面向切面编程(AOP):Spring支持面向切面编程。
- 事务管理:Spring对下至本地业务上至全局业务(JAT)提供了统一的事务管理接口。
- 异常处理:Spring提供一个方便的API将特定技术的异常(由JDBC, Hibernate, 或JDO抛出)转化为一致的、Unchecked异常。
依赖注入(DI)和控制反转(IOC)
- 控制反转(Inversion of Control)是一种是面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度。其基本思想是:借助于“第三方”实现具有依赖关系的对象之间的解耦。
- 依赖注入就是将实例变量传入到一个对象中去;好处:解耦,方便做单元测试。
- 两者的关系:依赖注入是一种设计模式,控制反转是一种思想。
Spring重要模块
- Spirng Core:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是BeanFactory,它是工厂模式的实现。BeanFactory使用控制反转模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
- Spring Context:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
- Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
- Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
- Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
- Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
Spring中的Bean有哪些作用域
- singleton:在Spring IOC容器中仅存在一个Bean实例,Bean以单例方式存在,默认(为了提高性能,减少内存消耗和垃圾回收)。
- prototype:每次从容器调用Bean时,都返回一个新实例,相当于执行new XxxBean()。
- request:每次HTTP请求都会创建一个新的Bean,该作用域仅适合用于WebApplicationContext环境。
- session:同一个HTTP Session共享一个Bean,不同Session使用不同Bean,仅适用于WebApplicationContext环境。
- globalSession:一般用于Portlet应用环境,该作用域仅适用于WebApplicationContext环境。
Spring 中的单例 Bean 的线程安全问题了解吗?
- 单例Bean存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。
- 解决方案:1.在Bean对象中尽量避免定义可变的成员变量(不太现实)、2.在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐)。
Spring中Bean的生命周期
Spring自动装配
- 默认情况下,default-autowire属性被设置为no,标示所有的Bean都不使用自动装配,需要装配使用ref属性。
- 开启自动装配:使用autowire属性设置自动装配类型,有byName、byType、constructor、autodetect。
@Resource、@Autowired和@Qualifier的区别
- @Resource:由JavaEE提供默认按名称进行装配,如果没有指定name属性,当注解写在字段上时默认取字段名进行名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,name属性一旦指定,只按照名称进行配置。
- @Autowired:由Spring提供默认按照类型装配,允许null值(设置required = false)),如果想使用名称装配可以结合使用@Qualifier注解。
- @Autowired自动注入底层原理:Spring在创建bean的过程中,最终会调用到doCreateBean()方法,在这个方法中会调用populateBean()方法,来为bean进行属性填充,完成自动装配等工作。在populateBean()方法中一共调用了两次后置处理器,第一次是对属性进行填充,第二次就会调用到AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues()方法,在该方法中就会进行@Autowired注解的解析,然后调用metadata.inject()方法,进行属性填充。
BeanFactory和ApplicationContext有什么区别?
- BeanFactory是工厂模式的一种实现,Spring 使用 BeanFactory 来实例化、配置和管理 Bean。XmlBeanFactory是BeanFactory的实现类,它根据XML文件中定义的内容加载beans。该容器从XML文件中读取配置元数据,并用它来创建一个完备的系统或应用。
- BeanFactorty接口提供了配置框架及基本功能,但是无法支持spring的aop功能和web应用。而ApplicationContext接口作为BeanFactory的派生,在功能上做了扩展:如事件传播特性,即支持aop特性、资源访问,如URL和文件、MessageSource, 提供国际化的消息访问等。
Spring IOC及初始化流程
- IOC(Inverse of Control)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。
- IOC 容器实际上就是个Map集合,负责实例化、定位、配置应用程序的对象及建立这些对象的依赖。
- IOC容器的初始化包括BeanDefinition的Resource定位、载入和注册这三个基本的过程。
- ClassPathXmlApplicationContext流程图:
Spring AOP
- AOP核心概念:1.横切关注点、2.切面(aspect)、3.连接点(joinpoint)、4.切入点(pointcut)、5.通知(dvice)、6.目标对象、7.织入(weave)、8.引入(introduction)。
- AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
- Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib ,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理。
- 在项目中的应用:事务管理、拦截器、日志处理。
Spring AOP 和 AspectJ AOP 有什么区别?
- Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
- Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,
- 如果切面比较少那么两者性能差异不大,但是当切面比较多的时候最好选择 AspectJ ,它比Spring AOP 快很多。
Spring事务
- 编程式事务,在代码中硬编码。(不推荐使用)
- 声明式事务(基于XML的声明式事务、基于注解的声明式事务),在配置文件中配置(推荐使用)
Spring事务管理有哪些优点
- 它为不同的事务API(如JTA, JDBC, Hibernate, JPA, 和JDO)提供了统一的编程模型。
- 它为编程式事务管理提供了一个简单的API而非一系列复杂的事务API(如JTA).
- 它支持声明式事务管理。
- 它可以和Spring 的多种数据访问技术很好的融合。
Spring事务的隔离级别
- ISOLATION_DEFAULT:这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
- ISOLATION_READ_UNCOMMITTED:它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
- ISOLATION_READ_COMMITTED:保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
- ISOLATION_REPEATABLE_READ:这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
- ISOLATION_SERIALIZABLE:这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
Spring事务传播行为
- PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认)
- PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
- PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常
- PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
- PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
- PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
- PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
Spring通知类型
- before:前置通知,在一个方法执行前被调用。
- after: 在方法执行之后调用的通知,无论方法执行是否成功。
- after-returning: 仅当方法成功完成后执行的通知。
- after-throwing: 在方法抛出异常退出时执行的通知。
- around: 在方法执行之前和之后调用的通知。
Spring框架用到了那些设计模式?请举例说明
- 代理模式 — 在 AOP 和 remoting 中被用的比较多 。
- 单例模式 — 在 spring 配置文件中定义的 bean 默认为单例模式 。
- 模板方法 — 用来解决代码重复的问题 。 比如 RestTemplate, JmsTemplate, JpaTemplate。
- 前端控制器 —Spring 提供了 DispatcherServlet 来对请求进行分发 。
- 视图帮助 (View Helper )—Spring 提供了一系列的 JSP 标签,高效宏来辅助将分散的代码整合在视图里 。
- 依赖注入 — 贯穿于 BeanFactory / ApplicationContext 接口的核心理念 。
- 工厂模式 —BeanFactory 用来创建对象的实例 。
Spring MCV是什么
- Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
Spring MCV优点
- 它是基于组件技术的.全部的应用对象,无论控制器和视图,还是业务对象之类的都是 组件.并且和 Spring 提供的其他基础结构紧密集成.
- 不依赖于 Servlet API(目标虽是如此,但是在实现的时候确实是依赖于 Servlet 的)3)可以任意使用各种视图技术,而不仅仅局限于 JSP4)支持各种请求资源的映射策略5)它应是易于扩展的
Spring MCV工作原理
- 客户端发送请求到 DispatcherServlet
- DispatcherServlet 查询 handlerMapping 找到处理请求的 Controller
- Controller 调用业务逻辑后,返回 ModelAndView
- DispatcherServlet 查询 ModelAndView,找到指定视图
- 视图将结果返回到客户端
Spring MCV处理流程
Spring MCV主要组件
- 前端控制器 DispatcherServlet(不需要程序员开发)作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
- 处理器映射器HandlerMapping(不需要程序员开发)作用:根据请求的URL来查找Handler
- 处理器适配器HandlerAdapter 注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。
- 处理器Handler(需要程序员开发)
- 视图解析器 ViewResolver(不需要程序员开发)作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)
- 视图View(需要程序员开发jsp)View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)
SpringMVC常用的注解有哪些?
- @Controller:使用它标记的类就是一个SpringMVC Controller 对象。
- @RequestMapping:是一个用来处理请求地址映射的注解,可用于类或方法上。
- @PathVariable:处理request url中的参数。
- @RequestParam:处理request body中的参数。
- @ResponseBody处理request body中的参数,并自动封装成一个对象。
- @Service、@Repositry:服务层和dao层注解。
- @ModelAttribute:该注解的方法会在Controller每个方法执行前被执行。
Spring MVC的异常处理 ?
- @Controller + @ExceptionHandler:配置对当前所在Controller的异常进行处理。
- @ControllerAdvice + @ExceptionHandler:配置对全局异常进行处理。
什么是MyBatis?
- Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。
- MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
- 通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。
MyBatis的优点
- 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
- 与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
- 很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。
- 能够与Spring很好的集成;
- 提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
MyBatis框架的缺点
- SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
- SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
MyBatis框架适用场合
- MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。
- 对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。
#{}和${}的区别是什么?
- #{}是预编译处理,${}是字符串替换。
- Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
- Mybatis在处理${}时,就是把${}替换成变量的值。
- 使用#{}可以有效的防止SQL注入,提高系统安全性。
当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
- 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致
- 通过<resultMap>来映射字段名和实体类属性名的一一对应的关系
模糊查询like语句该怎么写
- 在Java代码中添加sql通配符。
- 在sql语句中拼接通配符,会引起sql注入
Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
- Dao接口即Mapper接口。接口的全限名,就是映射文件中的namespace的值;接口的方法名,就是映射文件中Mapper的Statement的id值;接口方法内的参数,就是传递给sql的参数。
- Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MapperStatement。在Mybatis中,每一个 <select>、<insert>、<update>、<delete> 标签,都会被解析为一个MapperStatement对象。
- Mapper接口里的方法,是不能重载的,因为是使用 全限名+方法名 的保存和寻找策略。Mapper 接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理对象proxy,代理对象会拦截接口方法,转而执行MapperStatement所代表的sql,然后将sql执行结果返回。
Mybatis是如何进行分页的?分页插件的原理是什么?
- Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
- 分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
- 第一种是使用 <resultMap> 标签,逐一定义数据库列名和对象属性名之间的映射关系。
- 第二种是使用sql列的别名功能,将列的别名书写为对象属性名
在mapper中如何传递多个参数?
- 按顺序接收#{0}, #{1},不推荐
- @Param注解传参,推荐
- Java Bean传参,推荐
- @Map传参
如何获取自动生成的主键值?
- 通过属性
useGeneratedKeys
=
"true"
keyProperty
="xxxid",即可返回当前id
对于不支持自动生成主键的数据库还需添加<selectKey>标签。
Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不
- 动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。
- 9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。
- 原理:使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。
为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
- Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
- 而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。
MyBatis实现一对一有几种方式?具体怎么操作的?
- 有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;
- 嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。
MyBatis实现一对多有几种方式,怎么操作的?
- 有联合查询和嵌套查询。联合查询是几个表联合查询,只查询一次,通过在resultMap里面的collection节点配置一对多的类就可以完成;嵌套查询是先查一个表,根据这个表里面的 结果的外键id,去再另外一个表里面查询数据,也是通过配置collection,但另外一个表的查询通过select节点配置。
Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
- Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
- 它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
- 当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。
Mybatis的一级、二级缓存:
- 一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
- 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 <cache/> ;
- 对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。
什么是MyBatis的接口绑定?有哪些实现方式?
- 接口绑定,就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定, 我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。
- 接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定;另外一种就是通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。当Sql语句比较简单时候,用注解绑定, 当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多。
简述Mybatis的插件运行原理,以及如何编写一个插件。
- Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。
- 编写插件:实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。
Spring Boot是什么
- Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。
Spring Boot优点
- 非常简洁的安全策略集成。
- 支持运行期内嵌容器,如 Tomcat、Jetty。
- 强大的开发包,支持热启动、自动管理依赖、自带应用监控。
开启 Spring Boot 特性有哪几种方式?
- 继承spring-boot-starter-parent项目
- 导入spring-boot-dependencies项目依赖
Spring Boot 的核心配置文件及其格式
- 配置文件:application和bootstrap
- application主要用于 Spring Boot 项目的自动化配置,而bootstrap主要应用于Spring Cloud Config配置中心、一些固定的不能被覆盖的属性、一些加密/解密的场景。
- 格式:.properties和.yml
- 区别:1.书写方式不同、2.yml 格式不支持
@PropertySource
注解导入配置。
Spring Boot核心注解
- @SpringBootApplication:作用springboot启动类的注解,主要包含以下三个注解。
- @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
- @EnableAutoConfiguration:开启自动配置的功能,如需要关闭某些类的自动配置@SpringBootApplication(exclude = { xxx.class })。
- @ComponentScan:spring组件扫描。
Spring Boot 自动配置原理是什么?
- 其中 @EnableAutoConfiguration 是实现自动配置的入口,该注解又通过 @Import 注解导入了AutoConfigurationImportSelector,在该类中加载 META-INF/spring.factories 的配置信息。然后筛选出以 EnableAutoConfiguration 为 key 的数据,加载到 IOC 容器中,实现自动配置功能。
Spring Boot 如何定义多套不同环境配置?
- 提供多套配置文件,如:application-dev.yml
Spring Boot 如何设置支持跨域请求?
- 配置 CorsFilter Bean
- 继承WebMvcConfigurerAdapter重写addCorsMappings
Spring Boot 可以兼容老 Spring 项目吗,如何做?
- 可以兼容,使用
@ImportResource
注解导入老 Spring 项目配置文件。
比较一下 Spring Security 和 Shiro 各自的优缺点 ?
- 安全框架:认证功能、授权功能、加密功能、会话管理、缓存管理、rememberMe功能。
- Shiro:轻便简单灵活、功能相对完整。
- Spring Security:功能比shiro强大,与 Spring 全家桶有很好的兼容性,有更好的社区支持。
什么是微服务?
- 微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个微服务提供单位业务功能的服务,一个服务做一件事,从技术角度看就是一种小而独立的处理过程,类似进程概念,能够自行单独启动或销毁,拥有自己独立的数据库。(提出者:马丁福勒)
微服务有哪些特点?
- 解耦(Decoupling) - 系统内的服务很大程度上是分离的。因此整个应用可以被轻松构建、修改和扩展
- 组件化(Componentization) - 微服务被视为可以被轻松替换和升级的独立组件
- 业务能力(Business Capabilities) - 微服务非常简单,专注于单一功能
- 自治(Autonomy) - 开发人员和团队可以相互独立工作,从而提高效率
- 持续交付(ContinousDelivery) - 允许频繁发版,通过系统自动化完成对软件的创建、测试和审核,
- 责任(Responsibility) - 微服务不把程序作为项目去关注。相反,他们将程序视为自己负责的产品
- 分散治理(Decentralized Governance) - 重点是用正确的工具去做正确的事。这意味着没有任何标准化模式或着技术模式。开发人员可以自由选择最合适的工具来解决自己的问题
- 敏捷性(Agility) - 微服务支持敏捷开发。任何新功能都可以快速开发并被再次丢弃
设计微服务的最佳实践是什么?
- 为每个微服务分开数据存储
- 将代码保持在类似的成熟度等级上
- 为每个微服务进行单独的构建
- 部署到容器中
- 将服务器视为无状态的
微服务的优缺点分别是什么?
- 优点:高可靠、可扩展。
- 缺点:复杂度高、运维复杂、影响性能。
微服务中如何实现 session 共享 ?
- 将所有微服务的 session 统一保存在 Redis 上,当各个微服务对 session 有相关的读写操作时,都去操作 Redis 上的 session 。
什么是 SpringCloud?
- Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
- 为微服务提供一站式决绝方案。
SpringCloud和Dubbo
- SpringCloud是http协议传输,带宽会比较多,同时使用http协议一般会使用JSON报文,消耗会更大。
- Dubbo采用RPC通信,服务之间调用得性能会更好。
- springcloud相关组件多,有自己得注册中心网关等,集成方便,Dubbo需要自己额外去集成。
Rest和RPC对比
- RPC:远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。
- REST:是基于HTTP协议之上一组约束的一种设计风格。
微服务之间是如何独立通讯的?
- 同步:RPC,REST等
- 异步:消息队列。要考虑消息可靠传输、高性能,以及编程模型的变化等。
Ribbon和 Feign 的区别?
- Ribbon 和 Feign 都是客户端的负载均衡的工具,Feign的底层就是通过Ribbon实现的,它是对Ribbon的进一步的封装,让Ribbon 更加好用。
- Ribbon 使用HttpClient 或 RestTemplate 模拟http请求,步骤相当繁琐。
- Feign采用接口+注解的方式 ,将需要调用的其他服务的方法定义成抽象方法即可, 不需要自己构建http请求。然后就像是调用自身工程的方法调用,而感觉不到是调用远程方法,使得编写 客户端变得非常容易。类似于 mybatis 的 @Mapper注解 。
服务雪崩
- 多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的 “扇出” 。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”.
分布式集群下如何做到唯一序列号
- UUID,全局唯一(ID无序,影响性能)
- 数据库递增(分库分表时很难维护)
- redis 单线程特性,递增(集群复杂)
- 雪花算法(推荐)