Spring基本知识

100 阅读6分钟

1、Spring包含的模块

Core核心类库、Web模块、Test模块、ORM模块
Spring容器的启动过程?

2、@Controller和@RestController注解的区别
@Controller注解返回的是一个视图;
@RestController注解是一个复合注解:@ResponseBody + @Controller注解的组合,返回的是Json或者XML的数据

image.png

3、什么是Spring IoC

Spring IOC是指控制反转】依赖注入。意思是指创建bean依赖的属性bean的创建,这个动作由代码层交给spring容器进行管理和实现。

4、Spring bean的生命周期

xie.infoq.cn/article/de3…
这个是指spring bean的创建过程,主要包括:
获取bean定义——》实例化 ——》 属性注入———aware、postprocessor、———》初始化——》销毁

  • 获取bean定义:扫描工程内的bean,获取类定义的信息
  • 实例化:这一步也很简单,遍历上述Map,利用Bean定义里的无参构造方法创建对象,和new 对象同理
  • 属性注入:实例化的bean属性都是null,需要给其属性填充内容
  • 初始化:如果类实现了InitializingBean的话,则会执行overridemethod()

image.png

5、Spring中循环依赖的解决方案
循环依赖的场景:

  • AService对象中有BService的属性;BService对象中有AService的属性。在bean创建的过程中形成了循环依赖
    Spring使用三级缓存的方式解决循环依赖的问题,可以解决在setter方法注入时存在的循环依赖的问题,因为setter注入是在注入阶段,构造器注入的话是在初始化节点,无法解决这种情况的循环依赖。

6、Spring中三级缓存的作用?二级能不能解决问题?

xie.infoq.cn/article/de3…

三级缓存内容:

  • 一级缓存:缓存的是已经实例化、属性注入、完整的bean对象;
  • 二级缓存:缓存的是实例化、未完成属性注入的不完整的bean对象;
  • 三级缓存:缓存的是objectFactory,该factory主要是用于生成原始对象进行AOP的操作的代理对象。

Bean的创建流程:

  • 没有AOP操作的过程:

实例化bean ---> 生成原始对象-----> 属性注入 -----中间过程--->初始化 --->bean对象

  • 有AOP操作的过程:

image.png

如果 AService 方法中有 AOP 操作时,当 AService 的原始对象赋值(注入)给 BServiceAService 会进行 AOP 操作产生一个 代理对象,这个代理对象最后会被放入单例池(一级缓存)中,也就是说此时 BService 中注入的对象是原始对象,而 AService 最终创建的完成后是代理对象,这样就会导致 BService 依赖的 AService 和 最终的 AService 不是同一个对象

三级缓存解决的是

Spring通过三级缓存将出现循环依赖的AOP操作前置到了属性注入之前,确保了最终对象的一致

7、@Resource@Autowire的区别

@Resource是JavaEE的包下的,默认按照type类型进行装配

@Autowire是Spring框架下的,默认按照name方式进行装配

8、BeanFactory和FactoryBean的区别?

9、SpringMVC的实现原理是?

SpringMVC主要是用来处理请求响应的模块。映射请求路径,执行请求链路,返回请求结果。

主要流程:

  • 启动Tomcat

  • 解析项目配置的web.xml文件;

  • 创建并初始化DispatchServlet

  • DispathcServlet是一个Servlet,执行DispatchServletinit()方法

    • 里面包含Spring容器,创建Spring容器 -> initStrategies()方法

      • RequestMappingHandlerMapping Bean对象.afterPropertiesSet() ---->mappingRegistry()。查找出所有带@Controller、@RequestMappingHandler类,找出类里面带有请求路径的method保存起来,供后面请求访问时查询使用
      • BeanNameUrlHandlerMapping.initApplicationContext() ----> /*** 下面的Bean对象
      • RequestMappingHandlerAdapter.afterProperties() @ControllerAdvice注解 @InitBinder、@ModelAttributes这几个注解为后面请求参数解析、包装请求参数起作用
  • 处理请求:

    • DispatchServlet--->接收请求--->path,request paramter--->根据path定位class和method--->解析参数、参数绑定--->执行方法---->返回值包装@ResponseBody

HandlerMapping、Handler、Adaptor的区别

handlerMapping有3种,每一种都有不同的初始化方式,初始化完成之后会将path路径与handler(类/方法)映射关系保存下来

  • 根据请求响应取出handler、根据handler取出adapter的模式都是策略模式 image.png web.xml的配置
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contectConfigLocation</param-name>
          <param-value>/WEB-INF/spring.xml</param-value>  // 这个配置文件里面是扫描加载bean的路径配置
        </init-param>
        <load-on-startup>1</load-on-startup> // 1:代表启动tomcat就加载servlet;2:代表访问来了再加载
    </servlet>
    <servlet-mapping>
        <servlet-name>自定义的名字</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

10、SpringMVC的请求参数的注解

@RequestParam、@RequestBody请求体参数

11、SpringMVC返回的值的注解

@RestController:代表这个controller下面的所有方法返回的内容都是Json类型。content-type是application

SpringMVC配置文件中添加:<mvc:annotation-driven/>

12、在项目中如何实现的接口层统一返回和异常处理?

接口层统一返回可以用@ControllerAdvice注解定义一个处理类,实现ResponseBodyAdvice接口,将结果值包装成Json形式返回给前端

异常处理可以使用:

@RestControllerAdvice + @ExceptionHandler来进行处理

12、Spring AOP的实现原理?

<1> SpringAOP底层是基于代理对象实现的

@EnableAspectJAutoProxy(proxyTargetClass = true) // 强制使用CGLib实现代理

<aop:config proxy-target-class="true">
  <!-- 在其中配置AOP -->
</aop:config>

<2> Spring AOP中有几种Advice

概念术语:连接点(被拦截到的点)、切入点(对哪些连接点进行拦截)、通知advice(切入需要做的事情)

  • @Before 前置通知。方法执行前
  • @AfterReturning 后置通知。方法执行后
  • @After 最终通知。类似于finally
  • @AfterThrowing 异常通知。抛出异常的时候
  • @Around 环绕通知。方法执行前 + 方法执行后

<3> 切入点表达式:

execution(访问修饰符 )

<4> 动态代理的类型:

  • JDK动态代理:

    • 被代理的类需要实现接口才可以。被代理的类里继承自接口的才能有切面的织入,普通的方法切面是不会起作用的
    • 底层是基于反射实现的。底层生成的代理对象继承了Proxy类
  • CGLib动态代理

    • 生成了一个被代理类的子类
    • 缺点:final修饰的方法不能成功执行AOP切面内容

13、Spring事务

代码中使用@Transactional注解实现

Spring中事务的隔离级别的设置:

DEFAULT、 读未提交、读已提交、可重复读、串行化

事务的几个步骤:

1)获取数据库链接;

2)设置数据链接的autocommit =false;

3)执行数据库操作的CRUD;

4)执行 commit /rollback操作;

事务的传播类型:

public enum Propagation {
    REQUIRED(0),   // 支持当前事务,如果没有事务,新建一个「也是Spring默认的设置」
    SUPPORTS(1),   // 支持当前事务,如果没有事务,以非事务的方式运行
    MANDATORY(2),  // 支持当前事务,如果没有事务,抛出异常
    REQUIRES_NEW(3),    // 无论有没有都新建事务
    NOT_SUPPORTED(4),  // 非事务方式,如果有事务,则挂起
    NEVER(5),   // 以非事务方式运行,如果有事务,则抛出异常
    NESTED(6);
}