Spring

Bean线程安全问题

Spring中的Bean默认是单例的。可以使用@Scope注解设置将属性设置成prototype变成多例。

Spring中的Bean不是线程安全的

Spring Bean并没有可改变状态(例如Service类和Mapper类),所以在某种程度上说Spring的单例Bean是线程安全的。如果在bean中定义了可修改的成员变量,是要考虑线程安全问题的,可以使用多例或者加锁来解决。

AOP

AOP被称为面向切面编程,用于将那些与业务无关,但却会影响多个对象的公共代码和逻辑抽取并封装成为一个可重用的模块,这个模块被命名为”切面“(Aspect),减少系统中重复的代码,降低了模块之间的耦合度,同时提高系统的可维护性。

常见场景

  1. 记录操作日志。
  2. 缓存处理。
  3. Spring中内置事务处理。

事务原理

  1. 编程式事务:需要使用TransactionTemplate来实现。
  2. 声明式事务:AOP。

事务失效

  1. 异常捕获处理:方法内部给异常捕获了,会导致声明式事务感受不到异常。解决:在catch中再抛一个异常出去。
  2. 抛出检查异常:使用throws抛出异常。解决:配置@Transactional的属性rollbackFor=Exception.class
  3. 非public方法:方法没有使用public修饰。

Bean的生命周期

BeanDefinition

Spring容器在实例化时,会将xml配置的<bean>的信息封装成一个BeanDefinition对象,Spring根据BeanDefiniton来创建Bean对象,里面有许多属性来描述Bean。

  • beanClassName:bean的类名,到时候可以使用反射来创建。
  • initMethodName:初始化方法名称。
  • properyValues:bean的属性值。
  • scope:作用域
  • lazyInit:是否延迟初始化。

image-20230703122406424

自定义init方法是用@PostConstruct注解标注的方法。

循环依赖

依赖注入的时候,产生了环。

解决

三级缓存。其实只要二级就够了,但如果需要尝试代理对象,二级缓存是不够的。所以增加了三级缓存存放对象工厂,这个对象工厂就是用来创建目标对象的原始对象或者代理对象的。

缓存名称 源码名称 作用
一级缓存 singletonObjects 单例池,缓存已经经历了完整的生命周期,已经初始化完成的Bean对象。
二级缓存 earlysingletonObjects 缓存早期的Bean对象(生命周期还没走完)
三级缓存 singletonFactory 缓存的是Object Factory,表示对象工厂,用来创建某个Bean的。

image-20230703125044919

是无法直接解决构造方法注入产生的循环依赖的。只需要在循环依赖的其中一个类的构造方法参数上加一个@Lazy(延迟加载)注解就可以了。

SpringMVC

执行流程

  1. 在Web容器第一次使用的时候会创建DispatcherServlet对象及其调用init方法。init方法会创建Spring Web容器,并执行refresh方法。

    refresh方法过程中会创建并初始化Spring MVC中重要的组件,例如HandlerMappingHandlerAdapterHandlerExceptionResolverViewResolverMultipartResolver等。

    容器初始化后,会将上一步初始化好的主键复制给对于的DispatcherServlet成员变量。

  2. 用户发送请求到DispatcherServletDispatcherServlet会遍历所有的HandlerMapping,找到路径匹配的处理器。

    • HandlerMapping有多个,每个HanlderMapping会返回不同的处理对象,谁先匹配,就先返回谁的处理器。其中能识别的@RequestMapping优先级最高。
    • 对应@ResquestMapping的处理器是HandlerMethod,它包含了控制器对象和控制器方法。
    • 其中路径与处理器的映射在HandlerMapping初始化时就会建立好。
  3. 将HandlerMethod连同匹配到的拦截器,生成调用链对象HanlderExecutionChain返回(HandlerMenthd + 拦截器)

  4. 遍历HandlerAdapter处理器的适配器,找到能处理HandlerMethod的适配器对象,开始调用。

  5. 调用拦截器中的preHandle

  6. 有HandlerAdapter调用HandlerMethod

    1. 调用前处理不同类型的参数
    2. 调用后处理不同类型的返回值
  7. 第6步没有异常

    1. 返回ModelAndView
    2. 执行postHandle方法
    3. 解析视图,得到View对象,进行视图渲染。
  8. 第6步有异常,进入HandlerExeceptionResolver异常处理流程。

  9. 最后都会执行afterCompletion方法

  10. 如果返回的是json,则在6就会生成json结果,并标记ModelAndView已经处理,就不会执行7的视图渲染。

视图阶段

image-20230703153326977

  1. 用户发送请求到前端处理器DispatcherServlet。
  2. DispatcherServlet收到请求调用HandlerMapping(处理器映射器)
  3. HandlerMapping找到对应的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
  4. DispatcherServlet调用HandlerAdapter(处理器适配器)。
  5. HanlderAdapter经过处理器调用具体的处理器(Hanlder/Controller)。
  6. Controller执行完成后返回ModelAndView对象。
  7. HanderAdapter将Controller执行结构ModelAndView返回给DispatcherServlet。
  8. DispatcherServlet将ModelAndView传给ViewResolver(视图解析器)。
  9. ViewResolver解析后返回具体View(视图)。
  10. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
  11. DispatcherServlet响应用户。

前后端分离阶段

image-20230703153007435

  1. 用户请求到DispatcherServlet。
  2. DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。
  3. HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
  4. DispatcherServlet调用HandlerAdapter(处理器适配器)。
  5. HandlerAdapter经过处理器调用具体的处理器(Hanlder/Controller)。
  6. 方法上添加了@ResponseBody。
  7. 处理器通过HttpMessageConvention将返回结构转换为JSON响应。

SpringBoot

自动配置

自动配置:根据添加的依赖,会自动将一些配置类的bean注册进ioc容器,可以使用@Autowired@Resource等注解来使用它。

在SpringBoot项目引导类上有一个注解@SpringBootApplication,这个注解是对下面三个注解的封装。

@SpringBootConfiguration:该注解与@Configuration注解作用相同,用来声明当前类是配置类。

@ComponentScan:组件扫描,默认扫描该包及子包。

@EnableAutoConfiguration:SpringBoot实现自动化配置的核心注解。该注解下面有一个@Import({AutoConfigurationImportSelector.class})导入对应的配置选择器。内部就是读取了项目和引用jar包下classpath路径下META-INF/spring.factories文件中所配置的全部类名。在这些配置类中所定义的Bean会根据条件注解所指定的条件来决定是否需要将其导入到Spring容器中。

条件判断会有像@ConditionOnClass这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个配置类的所有Bean放入Spring容器中使用。

常见的注解

Spring

注解 说明
@Component、@Controller、@Service、@Repository 使用在类上,用于实例化Bean
@Autowired 使用在字段上,根据类型依赖注入
@Qualifier 结合@Autowired使用,根据名称依赖注入
@Scope 标注Bean的作用范围。单例还是多例。
@Configuration 指定当前类是一个配置类,创建容器时会从该类上加载注解。
@ComponentScan 指定Spring初始化时要扫描的包。
@Bean 使用在方法上,将该方法上返回的对象存储到Spring容器中
@Import 使用@Import导入的类会被存储到Spring容器中
@Aspect、@Before、@After、@Around、@Pointcut AOP相关,@Aspect切面类、@Before前置通知、@After后置通知、@Around环绕通知、@Pointcut切入点表达式。

SpringMVC

注解 说明
@RequestMapping 映射请求路径,定义在类上表示该类中所有方法都是以该地址作为父路径
@RequestBody 接受JSON请求数据,将JSON转换为Java对象
@RequestParam 指定请求参数的名称
@RequestHeader 获取指定请求头数据
@PathViriable 从请求路径上获取请求参数。
@ResponseBody 将Controller返回的对象转换为JSON响应
@RestController @Controller+@Response

SpringBoot

注解 说明
@SpringBootConfiguration 内部就是@Configuration
@EnableAutoConfiguration 打开自动配置功能,也可以关闭某个自动配置的选择。