Java各类技能知识点学习链接大全:五、Spring、Mybatis系列

五、Spring、Mybatis系列

 

1、Spring事务Transactional和动态代理(三)-事务失效的场景

Spring事务Transactional和动态代理(三)-事务失效的场景 - 骑着龙的羊 - 博客园

聊聊spring事务失效的12种场景,太坑了 - 苏三说技术 - 有趣.有料.硬核

2、springIoc:

Spring IoC有什么好处呢? - 知乎

3、Spring AOP——Spring 中面向切面编程

Spring AOP——Spring 中面向切面编程 - SharpCJ - 博客园

4、聊聊MyBatis缓存机制

聊聊MyBatis缓存机制 - 美团技术团队(美团技术博客)

《深入理解mybatis原理》 MyBatis的二级缓存的设计原理_我的程序人生(亦山札记)-CSDN博客_mybatis二级缓存原理

5、spring嵌套事务的处理:

spring 事务传播行为之嵌套事务NESTED细节 - 简书 (jianshu.com)

事务之六:spring 嵌套事务 - duanxz - 博客园

Spring中,多个service发生嵌套,事务是怎么样的? - 云+社区 - 腾讯云

Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法_levae1024的博客-CSDN博客_spring 嵌套事务
Spring事务传播机制Propagation.REQUIRES_NEW详解及测试_墨迹程序员-CSDN博客

6、spring的事务注解,为什么只对public方法生效?

java - Why doesn't Spring's @Transactional work on protected methods? - Stack Overflow

7、Spring 为啥默认把bean设计成单例的?

面试题:Spring为什么默认bean为单例? - 简书

8、Spring管理单例对象的时候,如何实现不被JVM回收的?

singletonObjects从属于ApplicationContext,只要ApplicationContext不被回收,singletonObjects就不会被回收。而ApplicationContext,就有多种情况了

① 你手动创建,例如在main方法中,那么生存周期根据你的代码而定。

② 整合到Servlet中,那么应用服务器持有ApplicationContext引用,服务器不关闭则引用不失效。

③ SpringBoot类似于①或②

若想springbean 被回收,可手动调用close方法,将bean 与容器关系隔离,即可回收;

spring容器不被gc的背后惊天秘密_syc_wwyxhqc的博客-CSDN博客

9、spring的BeanFactory和ApplicationContext有什么区别?

BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。

BeanFactory 简单粗暴,可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例。通常只提供注册(put),获取(get)这两个功能。我们可以称之为 “低级容器”。

(1)BeanFactory是Spring里面最底层的接口,是IoC的核心,定义了IoC的基本功能,包含了各种Bean的定义、加载、实例化,依赖注入和生命周期管理。ApplicationContext接口作为BeanFactory的子类,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能:

继承MessageSource,因此支持国际化。
资源文件访问,如URL和文件(ResourceLoader)。
载入多个(有继承关系)上下文(即同时加载多个配置文件) ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。
提供在监听器中注册bean的事件。
(2)①BeanFactroy采用的是延迟加载形式来注入Bean的,只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能提前发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。

        ②ApplicationContext,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 

        ③ApplicationContext启动后预载入所有的单实例Bean,所以在运行的时候速度比较快,因为它们已经创建好了。相对于BeanFactory,ApplicationContext 唯一的不足是占用内存空间,当应用程序配置Bean较多时,程序启动较慢。

(3)BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

(4)BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。

10、Spring 管理事务的方式有几种?   

(1)编程式事务,在代码中硬编码。(不推荐使用)        (2)声明式事务,在配置文件中配置(推荐使用)
                                                                                         声明式事务又分为两种:    a、基于XML的声明式事务    b、基于注解的声明式事务

大多数Spring框架的用户选择声明式事务管理,因为它对应用代码的影响最小,因此更符合一个无侵入的轻量级容器的思想。声明式事务管理要优于编程式事务管理;
声明式事务最大的优点就是不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明或通过@Transactional注解的方式,便可以将事务规则应用到业务逻辑中,减少业务代码的污染。唯一不足地方是,最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。

11、spring的事务传播机制:

spring事务的传播机制说的是,当多个事务同时存在的时候,spring如何处理这些事务的行为。事务传播机制实际上是使用简单的ThreadLocal实现的,所以,如果调用的方法是在新线程调用的,事务传播实际上是会失效的。

① PROPAGATION_REQUIRED:(默认传播行为)如果当前没有事务,就创建一个新事务;如果当前存在事务,就加入该事务。

② PROPAGATION_REQUIRES_NEW:意思是,创建一个新事务,如果当前存在事务,将这个事务挂起。也就是说如果当前存在事务,那么将当前的事务挂起,并开启一个新事务去执行REQUIRES_NEW标志的方法。
先来总结一下结果:
   结果一.标志REQUIRES_NEW会新开启事务,外层事务不会影响内部事务的提交/回滚
   结果二.标志REQUIRES_NEW的内部事务的异常,会影响外部事务的回滚

③ PROPAGATION_SUPPORTS:如果当前存在事务,就加入该事务;如果当前不存在事务,就以非事务执行。

④ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

⑤ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则按REQUIRED属性执行。

⑥ PROPAGATION_MANDATORY:如果当前存在事务,就加入该事务;如果当前不存在事务,就抛出异常。

⑦ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

12、Spring如何解决循环依赖问题

在创建bean的时候,首先想到的是从cache中获取这个单例的bean,这个缓存就是singletonObjects。如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取。如果还是获取不到且允许singletonFactories通过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取,如果获取到了则:从singletonFactories中移除,并放入earlySingletonObjects中。其实也就是从三级缓存移动到了二级缓存。

final Object bean = instanceWrapper.getWrappedInstance();//实例化
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))//缓存
populateBean(beanName, mbd, instanceWrapper);//填充属性

我觉得并不是实例化StudentA、StudentB、StudentC三个之后再去填充属性的。 实例化和填充属性的方法,都在doCreateBean中调用 对应的方法分别为,单线程执行顺序执行(遵循happens-before)。 比如先实例化了StudentA,他接着的动作是缓存StudentA,再去为StudentA填充属性,而并不先是实例化了ABC,在去为ABC填充属性。 在为StudentA填充属性的时候发现依赖了B,接着去实例化B -> 缓存B -> 为B填充属性 在为StudentB填充属性的时候发现依赖了C,接着去实例化C -> 缓存C -> 为C填充属性 在为StudentC填充属性的时候发现缓存中已经有了A的引用,这个时候直接从缓存中拿出来A为C填充了属性,此刻C已经完整了 接着将C填充到B的属性,在接着将B填充到A的属性,这样就解决了循环依赖 虽然没有显示调用递归方法,它是利用递归的思想走的流程;

Spring如何解决循环依赖问题_张维鹏的博客-CSDN博客_spring怎么解决循环依赖问题

一文告诉你Spring是如何利用"三级缓存"巧妙解决Bean的循环依赖问题的【享学Spring】 - 云+社区 - 腾讯云

13、为什么是三级缓存不是二级缓存:Spring 三级缓存解决bean循环依赖,为何用三级缓存而非二级_panda9527z的博客-CSDN博客_spring为什么用三级缓存而不是二级缓存

Spring 循环依赖及三级缓存_u012098021的博客-CSDN博客_spring三级缓存

上图来源自视频:阿里技术专家把Spring源码AOP、IOC、生命周期以及循环依赖讲全了_哔哩哔哩_bilibili 

 上图源自:4.Spring是如何解决循环依赖的问题的_哔哩哔哩_bilibili

14、SpringMVC Controller线程不安全?

SpringMVC Controller默认情况下是Singleton(单例),实现SpringMVC Controller线程安全,最简单粗暴的方法就是将Controller的scope定义为prototype,也就是说每次request过来时,都去创建新的instance,当然这么做的代价就是增大了系统开销,这似乎也违背了SpringMVC框架的初衷。

尽量不要在Controller中去定义变量属性。SpringMVC是基于方法的,通过形参传值,一个方法结束参数就销毁了。所以只要不在Controller中定义属性,那么Singleton(单例)是安全的。

15、SpringMVC  如何解决POST请求中文乱码问题,GET的又如何处理呢?

解决post请求乱码问题:在web.xml中配置一个CharacterEncodingFilter过滤器,设置成utf-8

 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

16、ApplicationContext通常的实现是什么
ClassPathXmlApplicationContext:此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找bean配置。
XmlWebApplicationContext:此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean。

17、Spring的自动装配:在spring中,使用autowire来配置自动装载模式,对象无需自己查找或创建与其相关对象,由容器负责把需要相互协作的对象引用赋予各个对象。

(1)在Spring框架xml配置中共有5种自动装配:

no:默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean。
byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean 的name 相同,就进行自动装配。 
byType:通过参数的数据类型进行自动装配。
constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
autodetect:自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。
(2)基于注解的自动装配方式:

使用@Autowired、@Resource注解来自动装配指定的bean。在使用@Autowired注解之前需要在Spring配置文件进行配置,<context:annotation-config />。在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性。在使用@Autowired时,首先在容器中查询对应类型的bean:

如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;

如果查询的结果不止一个,那么@Autowired会根据名称来查找;

如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false。

注:@Autowired和@Resource之间的区别:

a、 @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。

b、@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。

18、什么是基于Java的Spring注解配置? 给一些注解的例子:
(1)、基于Java的配置,允许你在少量的Java注解的帮助下,进行你的大部分Spring配置而非通过XML文件。

以@Configuration 注解为例,它用来标记类可以当做一个bean的定义,被Spring IOC容器使用。

另一个例子是@Bean注解,它表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文。
(2)、怎样开启注解装配?
注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在Spring配置文件中配置 <context:annotation-config/>元素。

(a)、@Component, @Controller, @Repository, @Service 有何区别?
@Component:这将 java 类标记为 bean。它是任何 Spring 管理组件的通用构造型。spring 的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。

@Controller:这将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。

@Service:此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用 @Service 而不是 @Component,因为它以更好的方式指定了意图。

@Repository:这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO 提供了额外的好处。它将 DAO 导入 IoC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException。

@Component是一个通用的Spring容器管理的单例bean组件。而@Repository, @Service, @Controller就是针对不同的使用场景所采取的特定功能化的注解组件。

因此,当你的一个类被@Component所注解,那么就意味着同样可以用@Repository, @Service, @Controller 来替代它,同时这些注解会具备有更多的功能,而且功能各异。

最后,如果你不知道要在项目的业务层采用@Service还是@Component注解。那么,@Service是一个更好的选择。

(b)、@Required 注解有什么作用
这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required注解的bean属性未被设置,容器将抛出BeanInitializationException


(c)、@Autowired 注解有什么作用
@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。@Autowired 注解提供了更细粒度的控制,包括在何处以及如何完成自动装配。它的用法和@Required一样,修饰setter方法、构造器、属性
@Autowired和@Resource之间的区别:
@Autowired可用于:构造函数、成员变量、Setter方法

(d)、@Autowired和@Resource之间的区别

@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。

@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。

(e)、@Qualifier 注解有什么作用

当您创建多个相同类型的 bean 并希望仅使用属性装配其中一个 bean 时,您可以使用@Qualifier 注解和 @Autowired 通过指定应该装配哪个确切的 bean 来消除歧义。

19、mybatis通过流式查询,防止过多查询数据量,导致系统OOM:

https://segmentfault.com/a/1190000022478915

20、mybatis分页查询:一种是前端每次传递pageNum和pageSiz,后台做相应计算,转换成mysql的limit m n 的方式。

(1)浏览器中分页显示,第一次查询时,需要先获取总页数,先从数据库中select count(1) 得到总条数,给total赋值,然后根据每页设置的大小pageSize,计算出总页数pageCount返回给前端展示。

        // 每页大小  pageSize
        int pageSize = 11;
        // 总条数  totolRecords
        int total = 0;
        // 总页数
        int pageCount=0;
        // 如果没有余数,当前页数,否则+1
        if (pageSize != 0) {
            if (total % pageSize != 0) {
                pageCount = total / pageSize + 1;
            } else {
                pageCount = total / pageSize;
            }
        }
        System.out.println("总页数:"+pageCount);

(2)再翻页,比如第二页的时候,前端传递当前页currentPage ,和pageSize,计算出limit m n 的值;

sql:

select * from table limit (currentPage-1)*pageSize,pageSize
//表示查询第一页的10条数据,也就是第1 -10条数据
select * from table limit 0,10;
  
//表示查询第二页的10条数据,也就是第11-20条数据
select * from table limit 10,10; 

21、参考链接以下中,其他方式:

mybatis自带的RowBounds方式:

RowBounds实现分页

原理:通过RowBounds实现分页和通过数组方式分页原理差不多,都是一次获取所有符合条件的数据,然后在内存中对大数据进行操作,实现分页效果。只是数组分页需要我们自己去实现分页逻辑,这里更加简化而已。

存在问题:一次性从数据库获取的数据可能会很多,对内存的消耗很大,可能导师性能变差,甚至引发内存溢出;

MyBatis精通之路之分页功能的实现(数组分页、sql分页、拦截器,RowBounds分页)_白哥哥的博客-CSDN博客_数组分页https://blog.csdn.net/chenbaige/article/details/70846902

22、PageHelper分页插件方式:

PageHelper.startPage()静态方法

//获取第1页,10条内容,默认查询总数count
    PageHelper.startPage(1, 10);

//紧跟着的第一个select方法会被分页
    List<Country> list = studentMapper.find();
    Page page = ((Page) list;

//获取第2页,10条内容,默认查询总数count

 // PageHelper.startPage(2, 10);

注:返回结果list,已经是Page对象,Page对象是一个ArrayList。
原理:使用ThreadLocal来传递和保存Page对象,每次查询,都需要单独设置PageHelper.startPage()方法。

public class SqlUtil implements Constant {
    private static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();
}

 参考贴:MyBatis使用PageHelper实现分页查询_pan_junbiao的博客-CSDN博客_mybatis分页pagehelper

PageHelper原理:MyBatis分页插件pagehelper的使用以及其原理源码_Morning sunshine的博客-CSDN博客_mybatis pagehelper使用

23、springboot面试题:

SpringBoot面试题整理,常问SpringBoot面试题汇总(2020版) - 工程师搁浅 - 博客园

SpringBoot常见的经典面试题_小陈之JAVA-CSDN博客_springboot面试题

24、详解SpringBoot——启动原理及自定义starter

视频讲解:

2021版最新SpringBoot2_权威教程_请直接从P112开始学习新版视频--置顶评论有直达链接-_雷丰阳_尚硅谷_哔哩哔哩_bilibili(自动配置:本地有配套资料)

尚硅谷SpringBoot顶尖教程(springboot之idea版spring boot)_哔哩哔哩_bilibili

尚硅谷SpringBoot顶尖教程(springboot之idea版spring boot)_哔哩哔哩_bilibili

博客:

SpringBoot启动流程原理+自动装配原理_yangxiaofei_java的博客-CSDN博客_springboot自动装配流程

SpringBoot启动全流程源码解析(超详细版)_July的博客-CSDN博客_springboot源码解析

SpringBoot启动流程解析 - 落日银河 - 博客园

以下图片来自于:SpringBoot启动全流程源码解析(超详细版)_July的博客-CSDN博客_springboot源码解析

25、springboot 2.3以后的优雅停机:

Spring Boot 2.3 新特性优雅停机详解_冷冷的博客-CSDN博客_springboot2.3优雅停机

26、spring注入接口还是实现类,同一接口有多个实现类,如何注入

spring注入接口还是实现类,同一接口有多个实现类,如何注入_q503385724的博客-CSDN博客_spring注入接口实现类

27、Spring系列第十九讲 @Configuration和@Bean注解详解

@Configuration,可以将其理解为一个Xml内容的Java版本

Spring系列第十九讲 @Configuration和@Bean注解详解 - 云+社区 - 腾讯云

28、@ConfigurationProperties

SpringBoot @ConfigurationProperties详解

SpringBoot @ConfigurationProperties详解 - 云+社区 - 腾讯云本文将会详细讲解@ConfigurationProperties在Spring Boot中的使用。https://cloud.tencent.com/developer/article/1657058

29、@EnableConfigurationProperties

关与 @EnableConfigurationProperties 注解 - 简书

30、EnableAutoConfiguration注解的工作原理

帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot,并创建对应配置类的Bean,并把该Bean实体交给IoC容器进行管理

但实际上重要的只有三个Annotation:

@Configuration(@SpringBootConfiguration点开查看发现里面还是应用了@Configuration)
@EnableAutoConfiguration
@ComponentScan

(本地参考资料:Spring Boot核心技术-笔记-pdf版)

帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot,并创建对应配置类的Bean,并把该Bean实体交给IoC容器进行管理

EnableAutoConfiguration注解的工作原理 - 简书

SpringBoot之@EnableAutoConfiguration注解_charming的专栏-CSDN博客_enableautoconfiguration

https://cloud.tencent.com/developer/article/1656324(长篇幅)

31、@Component 和 @Bean 的区别

(1).作用对象不同:@Component 注解作用于类,而 @Bean 注解作用于方法、(2).@Component 通常是通过路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用 @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。@Bean 注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean 告诉了 Spring 这是某个类的实例,当我们需要用它的时候还给我。

(3).@Bean 注解比 @Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解来注册 bean。比如想将第三方的类变成组件,你又没有没有源代码,也就没办法使用@Component进行自动配置,这种时候使用@Bean就比较合适了

原文链接:@bean注解和@component注解的区别_Spring 中的一些注解_我鸿的博客-CSDN博客

其他参考:@Component 和 @Bean 的区别_明明如月的技术博客-CSDN博客_bean和component的区别

32、Spring中Bean的生命周期

深究Spring中Bean的生命周期 - Java知音号 - 博客园

一文读懂 Spring Bean 的生命周期_riemann_的博客-CSDN博客

33、Spring中Bean的作用域

详解Spring中Bean的作用域与生命周期 - 华为云开发者社区 - 博客园

34、为什么 Spring Boot 的 jar 可以直接运行?

面试官:为什么 Spring Boot 的 jar 可以直接运行? - 简书

35、spring  IOC  的实现原理

Spring IOC 实现原理 - 简书

36、SpringBoot 究竟是如何跑起来的?

SpringBoot 究竟是如何跑起来的? - 知乎

37、Spring 事务 -- @Transactional的使用

Spring 事务 -- @Transactional的使用 - 简书

38、TCC分布式事务的实现原理

拜托,面试请不要再问我TCC分布式事务的实现原理!【石杉的架构笔记】

视频:【黑马】分布式事务解决方案专题_哔哩哔哩_bilibili

本地资料:微服务架构的分布式事务控制解决方案

39、SpringMVC流程:SpringMVC工作流程(详-小白版)_麦田里的守望者呀的博客-CSDN博客_springmvc工作流程

40、@Transactional注解在类上还是接口上使用,哪种方式更好?

回到问题上,在正确使用@Transactional注解时,不管@Transactional注解是在类上或实现类的方法上还是在接口上或接口方法上,它的事务功能都是可以实现的,只是选择那种方式更优雅一点而已。翻译过来大概意思是 Spring官方建议在具体的类或类的方法上使用@Transactional注解,而不是在接口或接口方法上使用。@Transactional也可以在接口上使用,但是这仅限于你使用的是基于接口的动态代理。在java中注解是不会被继承的,如果使用的是基于类的动态代理或者使用aspectj,@Transactional注解的作用就失效了。
@Transactional注解在类上还是接口上使用,哪种方式更好?_@transactional在类上_索码理的博客-CSDN博客

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值