I'm spiderman I'm spiderman
首页
  • 中间件
  • 基础架构
  • 微服务
  • 云原生
  • Java
  • Go
  • PHP
  • Python
  • 计算机网络
  • 操作系统
  • 数据结构
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档

spiderman

快乐学习,快乐编程
首页
  • 中间件
  • 基础架构
  • 微服务
  • 云原生
  • Java
  • Go
  • PHP
  • Python
  • 计算机网络
  • 操作系统
  • 数据结构
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
  • Java

    • Java基本原理
    • JVM原理
    • 线程
    • Spring原理
      • Mybatis和JPA
      • JVM调优
    • Golang

    • PHP

    • Python

    • 计算机语言
    • Java
    spiderman
    2022-12-20
    目录

    Spring原理

    # Spring原理

    # IOC理解

    1. 控制反转:原来由对象使用者控制的,有了spring后,整个生命周期由容器管理
    2. 依赖注入:将对应属性注入到具体对象中,用 @Autowired,@Resource,@PopulateBean 来完成属性填充
    3. 容器:使用map存储对象,在存储过程中有三级缓存,用 sigletonObjects 存储完整对象(一级), earlySigletonObject 存储半成品对象(二级), sigletonObjectFactory 存放lamba表达式和对象名称映射

    # 单例Bean和单例模式

    单例模式表示JVM中某个类的对象只会存在唯⼀⼀个。 ⽽单例Bean并不表示JVM中只能存在唯⼀的某个类的Bean对象。

    # Spring事务传播机制

    多个事务⽅法相互调⽤时,事务如何在这些⽅法间传播,⽅法A是⼀个事务的⽅法,⽅法A执⾏过程中调 ⽤了⽅法B,那么⽅法B有⽆事务以及⽅法B对事务的要求不同都会对⽅法A的事务具体执⾏造成影响, 同时⽅法A的事务对⽅法B的事务执⾏也有影响,这种影响具体是什么就由两个⽅法所定义的事务传播类 型所决定。

    1. REQUIRED(Spring默认的事务传播类型):如果当前没有事务,则⾃⼰新建⼀个事务,如果当前存 在事务,则加⼊这个事务
    2. SUPPORTS:当前存在事务,则加⼊当前事务,如果当前没有事务,就以⾮事务⽅法执⾏
    3. MANDATORY:当前存在事务,则加⼊当前事务,如果当前事务不存在,则抛出异常。
    4. REQUIRES_NEW:创建⼀个新事务,如果存在当前事务,则挂起该事务。
    5. NOT_SUPPORTED:以⾮事务⽅式执⾏,如果当前存在事务,则挂起当前事务
    6. NEVER:不使⽤事务,如果当前事务存在,则抛出异常
    7. NESTED:如果当前事务存在,则在嵌套事务中执⾏,否则REQUIRED的操作⼀样(开启⼀个事 务)

    # Spring事务什么时候会失效?

    spring事务的原理是AOP,进⾏了切⾯增强,那么失效的根本原因是这个AOP不起作⽤了!常⻅情况有 如下⼏种

    1. 发⽣⾃调⽤,类⾥⾯使⽤this调⽤本类的⽅法(this通常省略),此时这个this对象不是代理类,⽽是 UserService对象本身! 解决⽅法很简单,让那个this变成UserService的代理类即可!
    2. ⽅法不是public的:@Transactional 只能⽤于 public 的⽅法上,否则事务不会失效,如果要⽤在 ⾮ public ⽅法上,可以开启 AspectJ 代理模式。
    3. 数据库不⽀持事务
    4. 没有被spring管理
    5. 异常被吃掉,事务不会回滚(或者抛出的异常没有被定义,默认为RuntimeException)

    # Spring中的Bean创建的⽣命周期

    Bean的整个生命周期都是容器来控制的,其主要包含实例化和初始化

    1. 实例化Bean有 CreatBeanInstance 方法来生成对象
    2. 由 populateBean 来填充属性
    3. 向Bean对象中设置容器属性,会调用 invokeAwareMethods 方法来将容器对象设置到具体的Bean对象中 bean

    # Spring中Bean是线程安全的吗

    Spring本身并没有针对Bean做线程安全的处理

    所以:

    1. 如果Bean是⽆状态的,那么Bean则是线程安全的
    2. 如果Bean是有状态的,那么Bean则不是线程安全的
    3. 另外,Bean是不是线程安全,跟Bean的作⽤域没有关系,Bean的作⽤域只是表示Bean的⽣命周期范 围,对于任何⽣命周期的Bean都是⼀个对象,这个对象是不是线程安全的,还是得看这个Bean对象本 身

    # ApplicationContext和BeanFactory的区别

    BeanFactory是Spring中⾮常核⼼的组件,表示Bean⼯⼚,可以⽣成Bean,维护Bean,⽽ ApplicationContext继承了BeanFactory,所以ApplicationContext拥有BeanFactory所有的特点,也 是⼀个Bean⼯⼚,但是ApplicationContext除开继承了BeanFactory之外,还继承了诸如 EnvironmentCapable、MessageSource、ApplicationEventPublisher等接⼝,从⽽ ApplicationContext还有获取系统环境变量、国际化、事件发布等功能,这是BeanFactory所不具备的

    # Spring中的事务是如何实现的

    1. Spring事务底层是基于数据库事务和AOP机制的
    2. ⾸先对于使⽤了@Transactional注解的Bean,Spring会创建⼀个代理对象作为Bean
    3. 当调⽤代理对象的⽅法时,会先判断该⽅法上是否加了@Transactional注解
    4. 如果加了,那么则利⽤事务管理器创建⼀个数据库连接
    5. 并且修改数据库连接的autocommit属性为false,禁⽌此连接的⾃动提交,这是实现Spring事务⾮ 常重要的⼀步
    6. 然后执⾏当前⽅法,⽅法中会执⾏sql
    7. 执⾏完当前⽅法后,如果没有出现异常就直接提交事务
    8. 如果出现了异常,并且这个异常是需要回滚的就会回滚事务,否则仍然提交事务
    9. Spring事务的隔离级别对应的就是数据库的隔离级别
    10. Spring事务的传播机制是Spring事务⾃⼰实现的,也是Spring事务中最复杂的
    11. Spring事务的传播机制是基于数据库连接来做的,⼀个数据库连接⼀个事务,如果传播机制配置为 需要新开⼀个事务,那么实际上就是先建⽴⼀个数据库连接,在此新数据库连接上执⾏sql shiwu

    # Spring中什么时候@Transactional会失效

    因为Spring事务是基于代理来实现的,所以某个加了@Transactional的⽅法只有是被代理对象调⽤时, 那么这个注解才会⽣效,所以如果是被代理对象来调⽤这个⽅法,那么@Transactional是不会失效的。 同时如果某个⽅法是private的,那么@Transactional也会失效,因为底层cglib是基于⽗⼦类来实现 的,⼦类是不能重载⽗类的private⽅法的,所以⽆法很好的利⽤代理,也会导致@Transactianal失效

    # Spring容器启动流程是怎样的

    1. 在创建Spring容器,也就是启动Spring时:
    2. ⾸先会进⾏扫描,扫描得到所有的BeanDefinition对象,并存在⼀个Map中
    3. 然后筛选出⾮懒加载的单例BeanDefinition进⾏创建Bean,对于多例Bean不需要在启动过程中去进 ⾏创建,对于多例Bean会在每次获取Bean时利⽤BeanDefinition去创建
    4. 利⽤BeanDefinition创建Bean就是Bean的创建⽣命周期,这期间包括了合并BeanDefinition、推断 构造⽅法、实例化、属性填充、初始化前、初始化、初始化后等步骤,其中AOP就是发⽣在初始化 后这⼀步骤中
    5. 单例Bean创建完了之后,Spring会发布⼀个容器启动事件
    6. Spring启动结束
    7. 在源码中会更复杂,⽐如源码中会提供⼀些模板⽅法,让⼦类来实现,⽐如源码中还涉及到⼀些 BeanFactoryPostProcessor和BeanPostProcessor的注册,Spring的扫描就是通过 BenaFactoryPostProcessor来实现的,依赖注⼊就是通过BeanPostProcessor来实现的
    8. 在Spring启动过程中还会去处理@Import等注解 spring-start

    # Spring⽤到了哪些设计模式

    img

    # Spring Boot中常⽤注解及其底层实现

    1. @SpringBootApplication注解:这个注解标识了⼀个SpringBoot⼯程,它实际上是另外三个注解的 组合,这三个注解是: a. @SpringBootConfiguration:这个注解实际就是⼀个@Configuration,表示启动类也是⼀个 配置类 b. @EnableAutoConfiguration:向Spring容器中导⼊了⼀个Selector,⽤来加载ClassPath下 SpringFactories中所定义的⾃动配置类,将这些⾃动加载为配置Bean c. @ComponentScan:标识扫描路径,因为默认是没有配置实际扫描路径,所以SpringBoot扫 描的路径是启动类所在的当前⽬录
    2. @Bean注解:⽤来定义Bean,类似于XML中的bean标签,Spring在启动时,会对加了@Bean注 解的⽅法进⾏解析,将⽅法的名字做为beanName,并通过执⾏⽅法得到bean对象
    3. @Controller、@Service、@ResponseBody、@Autowired类似

    # AOP原理

    1. 对Bean进行扩展,在beanPostProcessor方法
    2. 用advice进行切面,切点
    3. 通过JDK或者cglib来生成代理对象
    4. 在方法调用中,会调用到生成字节码文件中直接找到DynamicAdvisoredInterceptor中的Interceptor方法,根据定义好的通知,来生成拦截器

    # Tomcat启动原理

    1. 启动spring容器
    2. @ConditionalOnClass来判断当前classpath中是否存在Tomcat依赖,如果存在则生成一个启动Tomcat的Bean
    3. 启动Tomcat的Bean,并创建Tomcat对象,并且绑定端口等,然后启动Tomcat

    # BeanFactory 和 FactoryBean区别

    BeanFactory必须严格遵守Bean的生命周期,创建单例Bean是流水式创建过程 FactoryBean可以自定义Bean对象创建流程,不需要遵循Bean生命周期,比如Feign

    # spring如何解决循环依赖

    三级闭环,提前暴露和aop

    # spring自动装配过程

    1. 通过各种注解实现了类与类之间的依赖关系,容器在启动的时候SpringApplication.run(),调用EnableAutoConfigurationImportSelector.class的selectImports方法
    2. selectImports方法调用SpringFactoriesLoader.loadFactoryNames方法扫描jar包类路径下的META-INF/spring.factories文件下,获取BeanConfiguration列表
    3. loadFactoryNames方法会读取spring.factories中EnableAutoConfiguration.class类名对应的值
    4. 根据这些类上的注解判断,若条件满足,则该配置类生效,将配置文件中自己设置的属性值配置到对应的配置类中,最后注入到IOC容器中实现自动配置

    总结 Spring Boot 通过@EnableAutoConfiguration开启自动装配,通过 SpringFactoriesLoader 最终加载META-INF/spring.factories中的自动配置类实现自动装配,自动配置类其实就是通过@Conditional按需加载的配置类,想要其生效必须引入spring-boot-starter-xxx包实现起步依赖

    #Spring
    线程
    Mybatis和JPA

    ← 线程 Mybatis和JPA→

    最近更新
    01
    innovation create future
    12-13
    02
    RabbitMQ
    12-06
    03
    StarRocks的应用
    09-11
    更多文章>
    Theme by Vdoing | Copyright © 2022-2024 spiderman | 粤ICP备2023019992号-1 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式