主流的 JAVA 技术
- Spring 全家桶
- Struts
- Apache ActiveMQ
- Mybatis
- Spark
- Hibernate
- JPA
- Shiro
- ……
Web 表示层
- struts
- spring web MVC
- Spring Web Flux
- JSF
- JAX-RS ( REST )
持久层
- iBatis
- Mybatis
- Hibernate
- JPA
- Spring JDBC
消息
- Apache ActiveMq
- RabbitMq
- RocketMq
- Kafka
RPC
- Dubbo
- Spring Cloud
议题
- 语言工具类拓展
- 集合工具类拓展
- JAVA SPI 拓展
java 非空判断
- Nulling : JSR 303 Not null 、JSR 308
@NonNull
- 集合非空
- Collection
- Map
- 数组非空
站在哲学的一定的高度上来思考这个问题。
为什么人都吃得了贫穷的苦,却吃不了学习的苦。
学习是一个主动吃苦的过程,而贫穷是一个被动的吃苦的过程。
你学习的时候,要查询很多文档。
开发的时候的意识
- 版本意识
- JAVA 7
- JAVA 8
- 依赖意识
- JAVA 6
- Spring
- Apache Commons-Lang
- JAVA 6
我们对主流框架非常的推崇。会对他们的编程模式不自觉地推崇
编程模式
-
Spring 事务
-
@Transational
-
1
<Bean id="" class=""/>
1 2 3
new Thread(()->{ });
-
你要站在一个很高地高度,高屋建瓴,不受制于某一个框架。
- 顶层设计能力
- 下层细节实现能力。
上层建筑决定系统的合理性,下层决定你的落地是不是实在。
很多架构师给你一个蓝图,但是行不行,他心里都没有谱。
How To Do ?
不知道怎么去做。
- Apache
- BCEL
- 字节码的提升
- BeanUtils
- 反射,java Beans 的东西。
- Cli
- 命令行解析
-D
-d
- 命令行解析
- Codec
- Collections
- 集合
- Compress
- 压缩
zip
tar
- 压缩
- Digester
- XML 的解析,只能用于解析 tomcat 里版用的多
- Lang
- 拓展
- BCEL
1
2
3
String name
int age
// 一个map 通过反射映射到这个类上边去。
Spring 只是一部分
1
2
3
4
5
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
StringUtils:
- apache
- isBlank
- Spring
- hasText
都有重复发明轮子。
如果你的依赖只有 Spring ,干脆就不要,不要重复的去实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
public class NullDemo {
public static void main(String[] args) {
Object object = null;
System.out.println(Objects.isNull(object));
}
/***
*Before 7
*/
private static boolean isnNull(Object object) {
return object == null;
}
}
org.springframework.util.StringUtils#parseLocale
1
2
3
4
5
6
7
8
9
10
11
@Nullable
public static Locale parseLocale(String localeValue) {
String[] tokens = tokenizeLocaleSource(localeValue);
if (tokens.length == 1) {
validateLocalePart(localeValue);
Locale resolved = Locale.forLanguageTag(localeValue);
return resolved.getLanguage().length() > 0 ? resolved : null;
} else {
return parseLocaleTokens(localeValue, tokens);
}
}
标准的 JAVA 的 API
你用一些顶层框架以后,屏蔽了很多细节,一个好的程序员要站在巨人的肩膀上,首先你要知道巨人的肩膀在哪里。爬到肩膀上去才能去做。
RabbitMq 新特性的文章看的人多。非主流技术的文章看的人少,
永远站在一个使用者的角度,而不是站在一个发明者的角度。所以永远不会提高。
多用才不会忘记!
很多工具类里边,你要去注意它的版本。 其实 Spring 做的不是很好。
API 推荐书籍 《Practical.API.Design.Confessions.of.a.Java.Framework.Architect》
JAVA Beans 的作者
什么是决定你是一个好的 API ?
- 二进制兼容
- 源代码兼容
它的书少看。Martin Fowler 把很多概念给转换了。
《Effective Java》
集合操作尽量返回非null;
书中讲 Array 不如 List
但是没有考虑性能问题。
下边这段代码创建了几个对象?
1
String value = "a" + "b";
@Since JAVA 7
StringBuilder 是一个对象before Java 7
String 是三个对象。
写代码非常的难。
你要考虑各种问题,站在设计的角度上
兼听则明,偏听则暗。
看文章,有些文章又对又不对的。
- ArrayList
- java 6 的时候, 10
- JAVA 7 的时候,是 null 的。
- JAVA 8 : 0 添加一个元素的时候,才是 10
Integer 有一个 cache,自动拆箱,装箱的。
是不是有缓存。
- JDK 1,7
- static 里边
- JDK 1.6
- InterCache 是一个内置类了。
-128~127 这个内存是可以调整的。
HashMap 算法改变了,
- < JDK 1.8
- 链表 + 数组 Hash Table
- 1.8 红黑树
不要被面试题!!!
先有技术,再有题目。
面试题可以参考一下,但是一定要有自己的方法。
java.util.Collections
如何生成一个一个元素的 Set
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class CollectionDemo {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
add();
}).start();
}
}
private static void add(){
// 线程安全吗?
Set<String> values = Collections.singleton("1");
// 线程安全吗?
Set<String> newValues = new ConcurrentSkipListSet<>();
values.add("1");
newValues.add("1");
}
}
这是一个并发的重进入的问题。
在方法里边怎么掉都是线程安全的。
你每个线程看到对象的状态是不一样的。
集合返回的时候,尽量返回不变的对象。
java.util.Collections#unmodifiableCollection
全部的都是只读。写的什么之类的都报错。
java.util.HashMap#values
返回的是集合的一个视图。只能看,不能改。浅 copy 的问题,也会有问题。
Arrays#mergeSort
- 1.6 堆排序
java.util.List#sort
- 1.7 会有一个阈值了。
- 1.8 有点类似
TimSort
每个 JAVA 版本都有区别。
1
2
3
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}
TreeMap 的 key 是可以比较的。
不是可比较的,就会编译失败。
TreeMap 的 key 不约束,是因为 可以把 Comparator
丢进去。
TreeMap -> Comparator
- Key1, key2
- comparator -> key1 instanceof Object
- Comparator -> key 咳哟 instanceof Comparable 相互比较
String
Integer
看你设计,工匠的心情。
开发仅仅是 4 则混合运算。
<k extends Comparable , V> == k class = Comparable.class or subClass
JAVA SPI
java Spi 有很多种
- ServiceLoder 机制
dubbo 的 SPI 类似
SPI = Service Provider Interface
SPI API
- Client SPI 提供实现
dubbo 的 SPI 是不是有 问题。
java.util.spi.ResourceBundleControlProvider
会解决 properties 的中文乱码的问题。
JAVA 6 里边提供了一个解决方案
jdk.internal.misc.JavaUtilResourceBundleAccess#getBundle
java.util.ResourceBundle.Control
会去取资源文件用的是 InputStream 字节流,就没有编码
META-INF/services
java.uitls.spi.ResourceBundlControlProvider
配置。
如果我有多个不同的实现,分发在不同的 jar
包得时候,怎么去设计。
abc=ABCLoadBalance
def=DEFLoadBalance
性能没有太大得影响,启动的时候就加载了。
java 只能通过顺序,区分,
Dubbo 的方式可以通过 key 去取
你没有比较,就不知道其中的
当多个 ClassLoader 的时候,你是不确定哪个是先加载,哪个是后加载的。
好的解决方案是
使用注解 @SPI("abc")
在框架的层面取校验
改变了我们的内部实现 SPI
类似于 AOP
的实现。
1
2
ResourceBundle DefaultControl 中文乱码
ResourceBundleControlProvider 替换掉 DefaultControl
我代码去读取的时候
- 旧方式:
- ResourceBundle.getBundle() -> DefaultControl-> 中文乱码
- 新方式:
- ResourceBundle.getBundle() -> control -> 中文正常
SPI
java
java.util.ServiceLoader
Spring
org.springframework.beans.factory.serviceloader.ServiceLoaderFactoryBean
1
2
3
4
5
6
7
8
9
10
11
12
public class ServiceLoaderFactoryBean extends AbstractServiceLoaderBasedFactoryBean implements BeanClassLoaderAware {
public ServiceLoaderFactoryBean() {
}
protected Object getObjectToExpose(ServiceLoader<?> serviceLoader) {
return serviceLoader;
}
public Class<?> getObjectType() {
return ServiceLoader.class;
}
}
Spirng 把我的 Service 当做了他的一个 Bean。
《Practical API Design》
一个是 java 的扩展机制,
Java 6 的 java.utils.ServiceLoader
书中的 serviceLoader 的 依赖注入是 JAVA 的依赖注入
国内的没有很牛逼的开源软件,但是讲起来某些技术头头是道。用的时候,用的淋漓尽致,创造的时候,创造不出来。