设计模式概述
简介在软件工程中,设计模式(design pattern)是对软件设计中普遍存在的各种问题,所提出的解决方案。设计模式并不是固定的一套代码,而是针对某一特定问题的具体解决思路与方案。可以认为是一种最佳实践,因为他是无数软件开发人员经过长时间的实践总结出来的。
提到设计模式不得不提《设计模式:可复用面向对象软件的基础》(Design Patterns – Elements of Reusable Object-Oriented Software) 一书。这本书由著名的四人帮——GoF(Gang of Four)编写,其中总结了23种设计模式,并将他们分成几个大类。
在 1994 年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版了一本名为 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 的书,该书首次提到了软件开发中设计模式的概念。
四位作者合称 GOF(四人帮,全拼 Gan ...
设计模式之模板模式
简介在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
何时使用:有一些通用的方法。
如何解决:将这些通用算法抽象出来。
关键代码:在抽象类实现,其他步骤在子类实现。
应用实例: 1、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。 2、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。 3、spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已经规范好的代码,直接丢一个实体就可以保存。
优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大 ...
阿里巴巴建议HashMap初始化时,指定容量大小?
为什么?关于集合类,《阿里巴巴Java开发手册》中写道:
我们先来写一段代码在JDK 1.7 (jdk1.7.0_80)下面来分别测试下,在不指定初始化容量和指定初始化容量的情况下性能情况如何。(jdk 8 结果会有所不同,我会在后面的文章中分析)
1234567891011121314151617181920212223242526272829303132333435public static void main(String[] args) { int aHundredMillion = 10000000; Map<Integer, Integer> map = new HashMap<>(); long s1 = System.currentTimeMillis(); for (int i = 0; i < aHundredMillion; i++) { map.put(i, i); } long s2 = System.currentTimeMillis(); ...
synchronized关键字的底层原理
synchronized 关键字底层原理属于 JVM 层⾯。
同步代码块
1234567public class SynchronizedDemo { public void method(){ synchronized (this){ System.out.println("Synchronized同步代码块"); } }}
使用java -v -p查看字节码文件
从上⾯我们可以看出:
synchronized 同步语句块的实现使⽤的是monitorenter和monitorexit指令,其中monitorenter指令指向同步代码块的开始位置, monitorexit指令则指明同步代码块的结束位置。
当执⾏monitorenter指令时,线程试图获取锁也就是获取对象监视器 monitor的持有权。
在 Java 虚拟机(HotSpot)中,Monitor 是基于 C++实现的,由ObjectMonitor实现的。每个对 象中都内置了⼀ ...
Java的HashMap死循环问题
HashMap源码分析
Java的HashMap是线程不安全的,所以在jdk1.7中,多线程的HashMap扩容采用头插法会发生死循环问题。
正常扩容当我们向HashMap中添加值的时候,调用的是Put()方法。
12345678910111213141516171819202122232425public V put(K key, V value) { //如果table数组为空数组{},进行数组填充(为table分配实际内存空间),入参为threshold, //此时threshold为initialCapacity 默认是1<<4(24=16) if (table == EMPTY_TABLE) { inflateTable(threshold); } //如果key为null,存储位置为table[0]或table[0]的冲突链上 if (key == null) return putForN ...
Spring事务详解
事务概念事务是数据库操作最基本单元,逻辑上的一组操作要么都成功。如果有一个失败所以操作都失败,回滚。
典型场景:银行转账。
特性事务必须服从ISO/IEC所制定的ACID原则。
特性
概念
A 原子性(atomicity)
表示事务执行过程中的任何失败都将导致事务所做的任何修改失效。
C 一致性(consistency)
表示执⾏事务前后,数据保持⼀致,多个事务对同⼀个数据读取的结果是相同的;
I 隔离性(isolation)
并发访问数据库时,⼀个⽤户的事务不被其他事务所⼲扰,各并发 事务之间数据库是独⽴的;
D 持久性(durability)
⼀个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发⽣故障也不应该对其有任何影响。
环境搭建创建一个Maven项目spring_tx
pom.xml12345678910111213141516171819202122232425262728293031323334353637<!--Druid--><dependency> <groupId>com.aliba ...
SpringBoot自定义starter
虽然SpringBoot官方给我提供了许多starter启动器,但是我们在工作开发中还是避免不了自定义启动器来简化我们的开发。
为此我们通过对SpringBoot自动配置原理的分析,我们要有
场景启动器starter
自动配置包autoconfigure
starter中没有任何代码,只是引入了当前场景我们所需的依赖。和最核心的一个自动配置包。
环境搭建首先我们创建一个空项目boot-09-customer-starter
自动配置包创建一个自动配置包kylin-hello-spring-boot-starter-autoconfigure模块。
这里我们没有其他功能,所以没有导入其他的启动器。
启动器接着在该项目中,创建一个启动器模块kylin-hello-spring-boot-starter。这里我们就直接创建一个Maven项目就行了(因为并不要写代码),只需引入相关依赖就行了。
爆红是因为我事先已经创好了。
接着我们要在我们的启动器中导入我们的自动配置包依赖。
12345<dependency> <groupId>com.kyli ...
SpringBoot自动配置原理分析
引导加载自动配置类我们从主启动程序入手分析。
12345678@SpringBootApplicationpublic class SpringbootApplication { public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); }}
这里标注了一个@SpringBootApplication注解,我们点击查看源码。
这个注解除了元注解,标注了三个其他的注解。
12345@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes ...
SpringBoot底层注解
@Configuration@Configuration标注上表明是一个配置类。@Bean标注在方法上,给容器中添加组件,方法名为组件ID,返回类型就是组件类型。返回值就是组件在容器中的实例。
首先创建两个bean,Pet和User
12345678910111213141516171819202122232425262728//宠物public class Pet { private String name; @Override public String toString() { return "Pet{" + "name='" + name + '\'' + '}'; } public String getName() { return name; } public void setN ...
SpringBoot场景启动器
场景启动器我们项目只导入了一个web开发的依赖。
1234<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency>
却导入了许多其他的依赖??这是因为这个就是web场景启动器。
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter查看官方文档可以发现。
All official starters follow a similar naming pattern; spring-boot-starter-*, where * is a particular type of application.
所有官方的启动器都遵循着一个命名规则就是spring-boot-start ...