Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions note/Dubbo/Dubbo底层源码学习——服务暴露.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
```
```Java
package org.apache.dubbo.rpc;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
Expand Down Expand Up @@ -33,7 +33,7 @@ public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
}
```

```
```Java
package org.apache.dubbo.rpc;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class ProxyFactory$Adaptive implements org.apache.dubbo.rpc.ProxyFactory {
Expand Down Expand Up @@ -71,7 +71,7 @@ public class ProxyFactory$Adaptive implements org.apache.dubbo.rpc.ProxyFactory
}
```

```
```Java
package org.apache.dubbo.remoting;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Transporter$Adaptive implements org.apache.dubbo.remoting.Transporter {
Expand Down Expand Up @@ -99,7 +99,7 @@ public class Transporter$Adaptive implements org.apache.dubbo.remoting.Transport
![export01](https://github.com/coderbruis/JavaSourceCodeLearning/blob/master/note/images/Dubbo/export01.png)

JavassistProxyFactory代码如下:
```
```Java
public class JavassistProxyFactory extends AbstractProxyFactory {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ dubbo://172.17.32.91:20880/org.apache.dubbo.demo.DemoService?anyhost=true&applic

先看下Dubbo中org.apache.dubbo.common包下的URL类源码:

```
```Java
public /*final**/
class URL implements Serializable {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ Java SPI的定义及使用步骤如下:
在com.test.spi包目录下,定义了一个PrintService接口和一个PrintServiceImpl实现类,然后在resources目录下定义了一个META-INF/services/com.test.spi.PrintService,注意这里定义的是一个
全路径名称的文件。

```
```Java
public interface Printservice (
void printlnfo();
}
```

```
```Java
public class PrintServicelmpl implements Printservice {
@Override
public void printlnfo() {
Expand All @@ -43,7 +43,7 @@ public class PrintServicelmpl implements Printservice {
}
```

```
```Java
public static void main(String[] args) (
ServiceLoader<PrintService> serviceServiceLoader =
ServiceLoader.load(PrintService.class);
Expand Down Expand Up @@ -119,7 +119,7 @@ ExtensionLoader即扩展点加载器,它是Dubbo SPI的核心,负责加载

上图清楚的展示了LoadingStrategy接口及其实现类的关系。LoadingStrategy继承了Prioritized,因而其实现类会有优先级之分,而Dubbo默认是使用的DubboInternalLoadingStrategy,查看其三个类的源码:

```
```Java
public class DubboInternalLoadingStrategy implements LoadingStrategy {

// 表示要加载的目录位置
Expand All @@ -136,7 +136,7 @@ public class DubboInternalLoadingStrategy implements LoadingStrategy {
}
```

```
```Java
public class DubboLoadingStrategy implements LoadingStrategy {

// 表示要加载的目录位置
Expand All @@ -160,7 +160,7 @@ public class DubboLoadingStrategy implements LoadingStrategy {
}
```

```
```Java
public class ServicesLoadingStrategy implements LoadingStrategy {

// 表示要加载的目录位置
Expand All @@ -185,7 +185,7 @@ public class ServicesLoadingStrategy implements LoadingStrategy {

这里的MAX_PRIORITY、NORMAL_PRIORITY和MIN_PRIORITY时定义在Prioritized这个接口中的,查看一下Prioritized中定义的值以及实现的compareTo方法:

```
```Java
/**
* The maximum priority
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

另外在@SPI注解的value值指定了扩展点默认的实现类名,例如SimpleExt注解由@SPI("impl1")修饰,则表示它的实现类名为:SimpleExtImpl1,查看SPI的配置文件可证:

```
```Java
# Comment 1
impl1=org.apache.dubbo.common.extension.ext1.impl.SimpleExtImpl1#Hello World
impl2=org.apache.dubbo.common.extension.ext1.impl.SimpleExtImpl2 # Comment 2
Expand All @@ -24,13 +24,13 @@ Dubbo通过ExtensionLoader去加载上述SPI配置文件,然后读取到@SPI("
Dubbo SPI的核心逻辑几乎都封装在ExtensionLoader之中,ExtensionLoader存放于dubbo-common模块的extension保重,功能类似于JDK SPI中的java.util.ServiceLoader。

下面展示了ExtensionLoader最常用的使用方式:
```
```Java
SimpleExt ext = ExtensionLoader.getExtensionLoader(SimpleExt.class).getDefaultExtension();
```

首先时调用ExtensionLoader#getExtensionLoader(SimpleExt.class),来获取SimpleExt类型的ExtensionLoader。查看ExtensionLoader源码如下:

```
```Java
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
if (type == null) {
throw new IllegalArgumentException("Extension type == null");
Expand All @@ -51,11 +51,11 @@ SimpleExt ext = ExtensionLoader.getExtensionLoader(SimpleExt.class).getDefaultEx
}
return loader;
}
```
```Java
getExtensionLoader方法首先回去判断EXTENSION_LOADERS缓存中是否已经缓存了该类型的扩展点加载器,如果没有则new一个该类型的ExtensionLoader并添加进EXTENSION_LOADERS中。但需要注意的是ExtensionLoader的构造方法
中,是会先创建默认的ExtensionFactory类型的ExtensionLoader对象,然后调用getAdaptiveExtension()方法创建适配类型的扩展点实现类。

```
```Java
private ExtensionLoader(Class<?> type) {
this.type = type;
// 从此处可以知道,对于默认的ExtensionFactory.class来说,是没有objectFactory熟悉对象值的
Expand All @@ -68,7 +68,7 @@ getExtensionLoader方法首先回去判断EXTENSION_LOADERS缓存中是否已经
被赋值为AdaptiveExtensionFactory。

下面看下getExtensionClass()方法的逻辑
```
```Java
private Class<?> getExtensionClass(String name) {
if (type == null) {
throw new IllegalArgumentException("Extension type == null");
Expand All @@ -81,7 +81,7 @@ getExtensionLoader方法首先回去判断EXTENSION_LOADERS缓存中是否已经
}
```

```
```Java
private Map<String, Class<?>> getExtensionClasses() {
Map<String, Class<?>> classes = cachedClasses.get();
// 双重检测,防止并发环境下指令重排序,cachedClasses是static类型
Expand All @@ -99,7 +99,7 @@ getExtensionLoader方法首先回去判断EXTENSION_LOADERS缓存中是否已经
}
```

```
```Java
private Map<String, Class<?>> loadExtensionClasses() {
// 缓存默认的扩展点名称,这里会去读取@SPI注解
cacheDefaultExtensionName();
Expand Down Expand Up @@ -140,7 +140,7 @@ getExtensionLoader方法首先回去判断EXTENSION_LOADERS缓存中是否已经
}
```

```
```Java
// 加载SPI配置文件目录
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
boolean extensionLoaderClassLoaderFirst, boolean overridden, String... excludedPackages) {
Expand Down Expand Up @@ -173,7 +173,7 @@ getExtensionLoader方法首先回去判断EXTENSION_LOADERS缓存中是否已经
}
```

```
```Java
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name,
boolean overridden) throws NoSuchMethodException {
if (!type.isAssignableFrom(clazz)) {
Expand Down Expand Up @@ -218,7 +218,7 @@ getExtensionLoader方法首先回去判断EXTENSION_LOADERS缓存中是否已经
![SPI_ADAPTIVE](https://github.com/coderbruis/JavaSourceCodeLearning/blob/master/note/images/Dubbo/spi_@Adaptive.png)

在ExtensionFactory接口上有@SPI注解修饰,而Dubbo会在调用ExtensionFactory时,会去调用ExtensionFactory的SPI配置文件中的扩展点名称以及扩展点实现类,查看下其SPI配置文件:
```
```Java
adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory
```
Expand All @@ -232,7 +232,7 @@ AdaptiveExtensionFactory会根据运行时状态来决定给ExtensionFactory赋

下面看下AdaptiveExtensionFactory类:

```
```Java
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

Expand Down Expand Up @@ -275,7 +275,7 @@ public class AdaptiveExtensionFactory implements ExtensionFactory {


下面看看ExtensionLoader的方法:
```
```Java
private Class<?> getAdaptiveExtensionClass() {
// 获取扩展点实现类,如果缓存中没有则去扫描SPI文件,扫描到扩展点实现类后则存入cachedClasses缓存中
getExtensionClasses(); // ------------------------ ②
Expand Down Expand Up @@ -325,7 +325,7 @@ public class AdaptiveExtensionFactory implements ExtensionFactory {
的扩展点实现类,就会去通过Javassist来生成代理代码,即生成对于的Xxx@Adaptive代码。

下面就是通过Javassist代理生产的适配类。(再Dubbo源码中的dubbo-common模块test目录下的org.apache.dubbo.extension包中有对应的测试类)
```
```Java
package org.apache.dubbo.common.extension.ext1;

import org.apache.dubbo.common.extension.ExtensionLoader;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@

接下来的原理分析通过Dubbo源码中的test包下的代码来进行说明。(想学好开源框架,要好好利用开源框架中各种Test用例)

```
```Java
@Test
public void test_getDefaultExtension() throws Exception {
SimpleExt ext = getExtensionLoader(SimpleExt.class).getDefaultExtension();
Expand Down
10 changes: 5 additions & 5 deletions note/JDK/一篇文章快速深入学习ThreadLocal.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
#### 2.1 ThreadLocal内部使用了哪些数据结构?
首先,我们来看下ThreadLocal中几个比较重要的数据结构。

```
```Java
/**
* 用于ThreadLocal内部ThreadLocalMap数据结构的哈希值,用于降低哈希冲突。
*/
Expand All @@ -135,7 +135,7 @@ private static int nextHashCode() {

下面将是ThreadLocal最终要的一个数据结构:ThreadLocalMap

```
```Java
/**
* ThreadLocalMap其实就是一个用于ThreadLocal的自定义HashMap,它和HashMap很像。在其内部有一个自定义的Entry类,
* 并且有一个Entry数组来存储这个类的实例对象。类似于HashMap,ThreadLocalMap同样的拥有初始大小,拥有扩容阈值。
Expand Down Expand Up @@ -197,7 +197,7 @@ static class ThreadLocalMap {

下面回到关于ThreadLocal源码的介绍,先看看set()和get()方法源码:

```
```Java
// ThreadLocal中的set()方法
public void set(T value) {
Thread t = Thread.currentThread();
Expand Down Expand Up @@ -244,7 +244,7 @@ static class ThreadLocalMap {



```
```Java
public T get() {
// 获取当前线程
Thread t = Thread.currentThread();
Expand Down Expand Up @@ -280,7 +280,7 @@ static class ThreadLocalMap {

知道怎么存储以及获取ThreadLocal之后,还要知道怎么清除ThreadLocal,防止内存泄漏,下面看下remove()源码:

```
```Java
// ThreadLocal的remove()方法
public void remove() {
// 获取当前线程中的ThreadLocalMap
Expand Down
8 changes: 4 additions & 4 deletions note/JDK/深入学习Java volatile关键字.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Lock引起的将当前处理器缓存该变量的数据写回到系统内存中
为了实现volatile的内存语义,编译期在生成字节码时会对使用volatile关键字修饰的变量进行处理,在字节码文件里对应位置生成一个Lock前缀指令,Lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成。

下面代码来演示一下禁止指令重排序:
```
```Java
a = 1; //语句一
b = 2; //语句二
flag = true; //语句三,flag为volatile变量
Expand Down Expand Up @@ -137,7 +137,7 @@ LoadLoad,StoreStore,LoadStore,StoreLoad实际上是Java对上面两种屏障的

下面来谈谈volatile的应用场景:
1. 状态标志:多个线程以一个volatile变量作为为状态标志,例如完成**初始化**或者**状态同步**。典型例子AQS的同步状态:
```
```Java
/**
* The synchronization state.
*/
Expand All @@ -146,7 +146,7 @@ private volatile int state;
2. 一次性安全发布

最典型的例子就是安全的单例模式:
```
```Java
private static Singleton instance;
public static Singleton getInstance() {
//第一次null检查
Expand All @@ -164,7 +164,7 @@ public static Singleton getInstance() {
上面这种写法,仍然会出现问题——多线程调用getInstance方法时,有可能一个线程会获得还**没有初始化的对象**!这都是因为重排序的原因,具体分析这里不展开。

解决办法及时用volatile对instance进行修饰
```
```Java
private static volatile Singleton instance;
```
这就是经典的“双重检查锁定与延迟初始化”。
Expand Down
Loading