前言
IDEA 文档插件 Doc View 又更新了新版本,本次更新版本如下:
支持在方法右键菜单选择 Doc Editor 直接编辑文档
编辑接口文档名称
编辑接口描述
编辑字段是否必填
编辑字段注释说明
点击确定, 会回写到源文件的注释中
支持在 Entity 中通过邮件菜单选择Doc Editor 编辑字段信息
编辑字段是否必填
编辑字段注释说明
点击确定, 会回写到源文件的注释中
支持将 Entity 复制为 Json 字符串
复制 Json 字符串时, 支持 Entity 中包含对象的转换
从 Doc View 预览界面直接跳转到编辑界面
是不是看着挺多的,下面,咱们就了解下具体都是什么吧!
Doc Editor
在方法右键菜单
弹起操作面板,可编辑参数如下:
接口名称:默认取方法名,当有注释且注释 tag 为 @docName 时,会取 @docName 对应的名称;
接口描述:取注释的描述内容;
请求/返回参数:请求返回参数的是否必填、描述。
下面使用动图演示:
在实体类右键菜单
在实体类中右键菜单,其实相当于方法中的请求/返回参数那一部分。
...
前言
原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。
通俗说法,就是将一个类作为原型,然后复制出来另一个类。
使用场景
这么一说,是不是发现我们经常使用?
比如咱们项目中有 BO、DTO、VO,但是在开发过程中,需要各种转换,get/set,一般情况下大家都会使用 BeanUtils,将一个类的属性值 set 到另一个类的属性值中,然后返回。
当然,也有一个实体直接从头捅到尾的。
关于 BeanUtils 的 copy 方法,各个框架都提供了相关工具,不过 Java 开发手册 有指出 Apache BeanUtils 性能较差、也推荐了其他框架。
这里介绍的是使用 Cglib BeanCopier。
封装工具类
查看文档,先封装一个工具类:
123456789101112131415161718public class BeanCopierUtils { private BeanCopierUtils() { } /** * 将source对象的属性拷贝到target对象中去 ...
前言
本文通过自定义模版,在 IDEA 中,通过简单的几个字符,快捷生成既定的代码。
示例
自定义模版
如何自定义模版
Windows and Linux
File -> Settings -> Editor -> Live Templates
macOS
IntelliJ IDEA -> Preferences -> Editor -> Live Templates
先添加一个 group,表示这里都是自己自定义的。
这个名字就自己随便取了,只要知道是自己的就可以。比如我的叫 My Template。
添加 Template 到自己创建的 group 里面
下面分别介绍里面的变量:
选项
描述
Abbreviation
缩写,需要用什么缩写唤起模版。
Description
描述,写不写都行。
Template Text
模版内容,这是关键!前后使用 $ 包裹的内容即变量 —— $变量$ 。
Applicable in
就是在哪一块生效,配置了这个就可以使用 ⌘+J 快捷唤起所有的在该处生效的 ...
前言
“工欲善其事,必先利其器。”
所以说今天来看一看如何压榨 IDEA ,让你的 IDEA 使用的更顺手!
今日技巧:
后缀完成
自定义后缀完成模版
示例
上面动图使用了 .sout .if 来举例,相信有些小伙伴在工作中经常使用。如果没有使用过,也可以🦑尝试一下。
自定义后缀模版
因为打印日志的时候,为了方便日志的查看,一般会将实体打印成 Json (性能问题先忽略)。
然后就可以使用这个方式来自定义后缀完成的模版。
是不是瞬间感觉方便很多了。
如何自定义后缀模版
Windows and Linux
File -> Settings -> Editor -> General -> Postfix Completion
macOS
IntelliJ IDEA -> Preferences -> Editor -> General -> Postfix Completion
总之,就是设置页面,找到 Postfix Completion, 不是(Live Templates)。
左下角有个 可以创建新的模版。
当 ...
前言
在循环依赖中有一种循环依赖,就是自注入:自己依赖自己。
事务的自注入
在 Spring 自调用事务失效,你是怎么解决的? 有小伙伴提出可以自己注入自己来解决事务失效。
具体使用方式如下:
1234567891011121314151617181920212223@Slf4j@Servicepublic class OrderBizServiceImpl implements OrderBizService { // 注入自己 @Autowired private OrderBizService orderBizService; @Override public void callBack() throws Exception { // 一系列的逻辑 // 需要事务操作更新订单和用户金额 orderBizService.updateOrderStatusAndUserBalance(); } @Override @Transactional(rollbackFo ...
前言
在研究 『 Spring 是如何解决循环依赖的 』 的时候,了解到 Spring 是借助三级缓存来解决循环依赖的。
同样在上一节留下了疑问:
循环依赖为什么要使用三级缓存?而不是使用二级缓存?
AOP 动态代理对循环依赖的有没有什么影响?
本篇文章也是围绕上面的内容进行展开。
笔记也在不断整理,之前可能会有点杂乱。
循序渐进,看一看什么是循环依赖?
开始先简单回顾一下 Bean 的创建过程,当然小伙伴也可以直接阅读『 单例 Bean 的创建 』这篇文章。
不过考虑到阅读本文前再阅读上一篇文章、Debug 等等,会比较耗时,所以本篇文章前面一小部分会先对之前的文章内容做简要概括,也相当于对我自己学习的知识进行一个总结。
先来回顾一下三级缓存的概念。
singletonObjects: 一级缓存,存储单例对象,Bean 已经实例化,初始化完成。
earlySingletonObjects: 二级缓存,存储 singletonObject,这个 Bean 实例化了,还没有初始化。
singletonFactories: 三级缓存,存储 singletonFactory。
B ...
前言
相信很多小伙伴在工作中都会遇到循环依赖,不过大多数它是这样显示的:
还会提示这么一句:
Requested bean is currently in creation: Is there an unresolvable circular reference?
老铁!这就是发生循环依赖了!
当然这里是一个异常情况。
在我的一篇文章中介绍如何避免 Spring 自调用事务失效,其中网友给建议,说可以在类中注入自身,然后调用,而注入自身的过程也是循环依赖的处理过程。
下面就一起看一看,什么是循环依赖,以及 Spring 是如何解决循环依赖的?
什么是循环依赖
Dependency Resolution Process
Spring IoC 容器会在运行时检测到构造函数注入循环引用,并抛出 BeanCurrentlyInCreationException。
所以要避免构造函数注入,可以使用 setter 注入替代。
根据官方文档说明,Spring 会自动解决基于 setter 注入的循环依赖。
当然在咱们工作中现在都使用 @Autowired 注解来注入属性。
PS: @Aut ...
前言
在 finishBeanFactoryInitialization 中介绍了创建 Bean 的流程大概流程,这里进入单例 Bean 的创建过程。
这里主要分为三个部分创建单例 Bean
getSingleton
createBean
getObjectForBeanInstance
下面进入源码:
getSingleton
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); // 加锁 synchronized (this.singletonObjects) ...
前言
可以说前面的都是准备工作,而接下来开始的才是重点,在这一步会完成 BeanFactory 的初始化,同时实例化单例 Bean。
具体怎么操作的,那就一起阅读源码吧!
不过在阅读源码之前,还是需要了解一些知识的。
什么是 FactoryBean ?
FactoryBean 是如何使用的 ?
Bean 是如何初始化的?
常说的循环依赖是怎么解决的?
什么是 FactoryBean ?
在官网的这篇文章《What’s a FactoryBean?》中有相关解答,有兴趣的小伙伴可以看一下。
由内部使用的对象实现的接口,这些对象 BeanFactory 本身就是单个对象的工厂。如果 bean 实现此接口,则它将用作对象公开的工厂,而不是直接用作将自身公开的 bean 实例。
注意:实现此接口的 bean 不能用作普通 bean。 FactoryBean以 bean 样式定义,但是为 bean 引用(getObject())公开的对象始终是它创建的对象。
FactoryBeans 可以支持单例和原型,并且可以按需延迟创建对象,也可以在启动时急于创建对象。
当生命一个 FactoryBea ...
前言
上一篇介绍了国际化的使用以及初始化消息源的源码,接下来接着往下阅读,将进入 initApplicationEventMulticaster 、onRefresh 和 registerListeners 的相关操作逻辑。
这一部分主要是初始化事件广播器以及注册监听器。而 onRefresh 部分则需要子类去实现。 所以本文主要介绍以下几个部分:
什么是 Spring 事件?
监听器是如何使用的?
什么是 Spring 事件?
这块的介绍在官网 1.15.2. Standard and Custom Events 部分有介绍。
Spring 通过 ApplicationEvent 类和 ApplicationListener 接口提供 ApplicationContext 中的事件处理。如果将实现 ApplicationListener 接口的 bean 部署到上下文中,则每次将 ApplicationEvent 发布到 ApplicationContext 时,都会通知该 bean。本质上,这是标准的观察者设计模式。
归纳下来主要就是三个部分: 事件、事件发布者、事件监听 ...
前言
在阅读完 registerBeanPostProcessors 源码之后, 下一步就进入到 initMessageSource,这一步主要作用是初始化国际化文件。
依然如之前所示,先通过官网了解到国际化的用法,然后再对源码进行研究。
MessageSource 国际化
如官网1.15.1. Internationalization using MessageSource所示,主要作用就是使用国际化,定制不同的消息。
需要注意的是 MessageSource 定义的 Bean 名字必须为 messageSource, 而如果找不到则会默认注册 DelegatingMessageSource 作为 messageSource 的 Bean。
使用
1. 创建国际化文件
2. 声明 MessageSource
在 JavaConfig 中 声明 MessageSource , 记得名字一定要叫做 messageSource !
12345678910111213141516@Configuration@ComponentScan("com.liuzhihang&qu ...
前言
前面通过 invokeBeanFactoryPostProcessors 这一步了解到了什么是 BeanFactoryPostProcessor ,以及 BeanFactoryPostProcessor 的使用及作用,并通过 invokeBeanFactoryPostProcessors 这一步源码,对 BeanFactoryPostProcessor 的加载流程有了进一步了解。
现在就一起进入下一个环节:
registerBeanPostProcessors(beanFactory);
这一步主要的作用是加载 BeanPostProcessor,从名字也可以看出,只是加载,并没有执行。
不过,在进入源码之前,依然是结合官网,先了解以下几个问题:
什么是 BeanPostProcessor?
BeanPostProcessor 是如何使用的?
BeanPostProcessor 有什么用?
什么是 BeanPostProcessor ?
如截图所示,在官网 1.8.1 Customizing Beans by Using a BeanPostProcessor 中介绍, B ...