博文

【不懂就问】MyBatis的一级缓存竟然还会引来麻烦? - 掘金

图片
【不懂就问】MyBatis的一级缓存竟然还会引来麻烦? - 掘金 LinkedBear 2020年06月28日 阅读 1252 【不懂就问】MyBatis的一级缓存竟然还会引来麻烦? 【 “不懂就问” ,是一个新的系列,主要整理我的小册群里遇到的一些比较有意思的 / 有难度的 / 容易被讨论起来的问题,并给出问题的解析和方案等等。喜欢的小伙伴们可以点赞关注我鸭 ~ ~ 学习源码可以看看我的小册 ~ ~】 端午假期相信不少小伙伴都在偷偷学习吧(说好了放假一起玩耍呢,结果又背着我学习),这不,刚过了端午,我的一个沙雕程序猿圈子里就有人讨论起来问题了,这个问题聊起来好像挺麻烦,但实际上问题是很简单的,下面咱来讨论下这个问题。 原问题 MyBatis 一级缓存与 SpringFramework 的声明式事务有冲突吗?在 Service 中开启事务,连续查询两次同样的数据,结果两次查询的结果不一致。 —— 使用 Mapper 的 selectById 查出来实体,然后修改实体的属性值,然后再 selectById 一下查出来实体,对比一下之前查出来的,发现查出来的是刚才修改过的实体,不是从数据库查出来的。 —— 如果不开启事务,则两次请求查询的结果是相同的,控制台打印了两次 SQL 。 初步分析 讲道理,看到这个问题,我一下子就猜到是 MyBatis 一级缓存重复读取的问题了。 MyBatis 的一级缓存默认开启,属于 SqlSession 作用范围。在事务开启的期间,同样的数据库查询请求只会查询一次数据库,之后重复查询会从一级缓存中获取。当不开启事务时,同样的多次数据库查询都会发送数据库请求。 上面的都属于基础知识了,不多解释。重点是,他修改的实体是 直接从 MyBatis 的一级缓存中查询出来的 。咱都知道,查询出来的这些实体肯定属于对象,拿到的是对象的引用,咱在 Service 里修改了,一级缓存中相应的也就会被影响。由此可见,这个问题的核心原因也就很容易找到了。 问题复现 为了展示这个问题,咱还是简单复现一下场景吧。 工程搭建 咱使用 SpringBoot + mybatis-spring-boot-starter 快速构建出工程,此处 SpringBoot 版本为 2.2.8 , myb...

深夜加班无聊,基于反射仿了个EventBus - 掘金

图片
深夜加班无聊,基于反射仿了个EventBus - 掘金 饭谈编程 2020年06月29日 阅读 179 深夜加班无聊,基于反射仿了个EventBus 干货点 通过阅读该篇博客,你可以了解了解java的反射机制、可以了解如何基于spring生命周期使用自定义注解解决日常研发问题。 问题描述 在日常研发中,经常会遇见业务A的某个action被触发后,同时触发业务B的action的行为,这种单对单的形式可以直接在业务A的action执行结束后直接调用业务B的action,那么如果是单对多的情况呢? 方案解决 这里提供一种在日常研发中经常使用到的机制,基于spring实现的事件驱动,即在业务A的action执行完,抛出一个事件,而业务B、C、D等监听到该事件后处理相应的业务。 场景范例 这里提供一个场景范例,该范例基于springboot空壳项目实现, 具体可以查看源码 ,此处只梳理关键步骤。 步骤一: 定义一个注解,标志接收事件的注解,即所有使用了该注解的函数都会在对应事件被抛出的时候被调用,该注解实现比较简单,代码如下 /** * @author xifanxiaxue * @date 3/31/19 * @desc 接收事件的注解 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface ReceiveAnno { // 监听的事件 Class clz(); } 复制代码 定义事件接口 /** * @author xifanxiaxue * @date 3/31/19 * @desc */ public interface IEvent { } 复制代码 所有事件都需要实现该接口,主要是为了后面泛型和类型识别。 定义MethodInfo /** * @author xifanxiaxue * @date 3/31/19 * @desc */ public class MethodInfo { public Object obj; public Method method; public static Metho...

什么是扩展 | Chrome 扩展(插件) 开发教程

图片
什么是扩展 | Chrome 扩展(插件) 开发教程 什么是扩展 | Chrome 扩展(插件) 开发教程 https://dev.crxhome.org/guide/what-is-extensions.html#%E4%BB%80%E4%B9%88%E6%98%AF%E6%89%A9%E5%B1%95 Chrome 扩展(插件) 开发教程 最新 Chrome 扩展官方文档教程中文版 Tags: published June 29, 2020 at 05:54PM Open in Evernote

三年Java开发经验,连如何动态注册bean都不知道 - 掘金

图片
三年Java开发经验,连如何动态注册bean都不知道 - 掘金 饭谈编程 2020年06月29日 阅读 225 三年Java开发经验,连如何动态注册bean都不知道 干货点: 看完该篇文章我们可以了解到为何要动态注册bean、动态注册bean的方式、注册和实例化的区别、spring是什么时候实例化bean的。 描述: 前阵子在给项目写组件的时候研究了下spring组件拓展流程,其中遇见了动态注册bean的操作,对于长期使用spring容器管理bean的同学来说动态注册bean应该是活久见系列,为此打算以组件中使用到的方式讲讲动态注册方面的相关解说。 应用场景 在自定义组件的时候,需要自定义命名空间注册器,其中需要提供一个配置解析器ConfigDefinitionParser,配置解析器需要继承AbstractBeanDefinitionParser, 其中需要重写函数parseInternal,返回的是AbstractBeanDefinition类型的数据。为了返回AbstractBeanDefinition,我借鉴了其他spring内部组件的写法,这边就用到了动态注册bean了。 在进入动态注册bean的相关解说前之前有必要大致描述下spring容器注册bean的相关知识! 了解下DefaultListableBeanFactory DefaultListableBeanFactory是spring容器注册bean的核心,是spring注册及加载bean的默认实现。 一句话来描述其应用那就是:在spring项目启动的时候通过DefaultListableBeanFactory注册所有的BeanDefinition后放入definition表,后面在我们使用的时候就可以直接从表中加载了。 了解下BeanDefinition 在说到动态注册bean之前,要先提下BeanDefinition 这是从官方文档截出来的,对此我的理解是,BeanDefinition是bean在实例化之前存在spring容器中的一种状态。 分不清注册和实例化的同学们在这里内心应该是 ━━( ̄ー ̄*|||━━ wocao,实例化和注册,什么跟什么 。 别急,在文章最后会点一下实例化和注册的哈! 大致了解了这两个之后便...

Spring Bean初始化的几种常规方式 - 掘金

图片
Spring Bean初始化的几种常规方式 - 掘金 入门小站 2020年06月28日 阅读 112 Spring Bean初始化的几种常规方式 通过构造方法实例化 通过静态工厂实例化 通过实例工厂实例化 通过FactoryBean实例化 RumenzA实体类 java package com.rumenz; public class RumenzA { private String id; private String name; public static RumenzA createRumenzA () { RumenzA rumenzA= new RumenzA(); rumenzA.setId( "123" ); rumenzA.setName( "入门小站" ); return rumenzA; } public RumenzA () { System.out.println( "RumenzA 无参构造方法" ); } public RumenzA (String id) { this .id = id; System.out.println( "ID构造方法" ); } // set get省略 } 复制代码 构造方法 beans.xml xml <? xml version= "1.0" encoding= "UTF-8" ?> < beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://www.springfr...