2021SC@SDUSC
一、代码分析内容
本次博客介绍ActiveJ的inject模块的最后一个包:impl包。impl就是implement的缩写,从名字就可以看出,这个包是为了实现某些接口的。下面我们可以通过查看imp包的结构,更直观地看出它是实现什么接口的。
二、impl包结构
我们可以看到,impl包基本都是和binding相关的,也就是说这个是为了实现与binding功能相关的接口。包里面有AbstractCompiledBinding、AbstractRootCompiledBinding、AbstractUnsyncCompiledBinding、BindingInitializer、Preprocessor这五个类和BindingInitializerCompiler、BindingLocator、CompiledBinding、CompiledBindingInitializer、CompiledBindingLocator这五个接口。
其中有三个类AbstractCompiledBinding、AbstractRootCompiledBinding、AbstractUnsyncCompiledBinding都是为了实现CompiledBinding接口,这几个接口也有互相调用的情况。
三、代码解读
我们首先来看一下这几个接口。
1.CompiledBinding类
这个类被impl包中的三个类所实现,那么它应该是比较重要的一个类。
这被定义为一个抽象类,而不是一个函数接口,因此任何匿名类的使用都被编译为一个内部类,而不是带有动态调用指令的方法。出现这种情况是编译后的绑定适用于以后专门化所必需的。
下面是CompiledBinding创建的一个对象,这个对象定义了getInstance方法,因为这是一个抽象类,所以并没有直接写明具体实现方法
CompiledBinding<?> MISSING_OPTIONAL_BINDING = new CompiledBinding<Object>() {
@Override
public Object getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) {
return null;
}
};
这个类的最后是返回上面创建的对象。
static <R> CompiledBinding<R> missingOptionalBinding() {
return (CompiledBinding<R>) MISSING_OPTIONAL_BINDING;
}
2.BindingLocator类
当尝试生成绑定时,此函数将传递给BindingGenerator。
生成器可以依赖于其他绑定,这些绑定不存在,但可以生成。
此函数用作递归的一种方法——当不存在请求的绑定时,它会尝试生成它,并从生成器本身调用它。
检索给定键的现有绑定,或尝试从已知的{@link BindingGenerator}递归生成它。
类代码如下:
@FunctionalInterface
public interface BindingLocator {
<T> @Nullable Binding<T> get(Key<T> key);
}
3.CompiledBindingLocator类
这个类从类名上看好像是和上一个接口有关,是用来编译BindingLocator的,但这个接口实际上是调用了CompiledBinding,使用get方法来获取key。
public interface CompiledBindingLocator {
<Q> @NotNull CompiledBinding<Q> get(Key<Q> key);
}
4.BindingInitializerCompiler类
impl包中许多方法是一环套一环的,BindingInitializerCompiler类的参数就是上面刚提到的CompiledBindingLocator创建的compileBindings。
这个类是用来绑定初始化编译器的。
@FunctionalInterface
public interface BindingInitializerCompiler<R> {
CompiledBindingInitializer<R> compile(CompiledBindingLocator compiledBindings);
}
5.CompiledBindingInitializer类
要注意的是,CompiledBindingInitializer类是一个抽象类而不是接口,原因与上述的CompiledBinding相同。
这是一个初始化器,它定义了一个initInstance方法但没有实现。
public interface CompiledBindingInitializer<R> {
void initInstance(R instance, AtomicReferenceArray[] instances, int synchronizedScope);
}
上面是几个interface的类,有的是接口,有的是抽象类,下面介绍剩下的几个类。
6.AbstractCompiledBinding类
这个类实现了CompiledBinding抽象类,它的构造方法如下:
protected AbstractCompiledBinding(int scope, int index) {
this.scope = scope;
this.index = index;
}
上面提到,CompiledBinding类定义了getInstance方法,在这里,getInstance实现如下:
public final R getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) {
AtomicReferenceArray array = scopedInstances[scope];
R instance = (R) array.get(index);
if (instance != null) return instance;
if (synchronizedScope == scope) {
instance = doCreateInstance(scopedInstances, synchronizedScope);
array.set(index, instance);
return instance;
}
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (array) {
instance = (R) array.get(index);
if (instance != null) return instance;
instance = doCreateInstance(scopedInstances, scope);
array.set(index, instance);
return instance;
}
}
这里创建了一个AtomicReferenceArray数组对象并且是scopedInstances的多态,并创建instance实例,经过复制之后返回instance。
7.AbstractRootCompiledBinding类
这个类也是实现CompiledBinding抽象类的,但是和AbstractCompiledBinding类还是有不同的。它创建的属性就与之不同:
private volatile R instance;
protected final int index;
protected AbstractRootCompiledBinding(int index) {
this.index = index;
}
instance是下面实现getInstance中要用到的。这一个实现与上一个有明显的不同,没有创建scopedInstances数组,而是将instance赋值给localInstance。
public final R getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) {
R localInstance = instance;
if (localInstance != null) return localInstance;
synchronized (this) {
localInstance = instance;
if (localInstance != null) return localInstance;
localInstance = (R) scopedInstances[0].get(index);
if (localInstance != null) return instance = localInstance;
instance = doCreateInstance(scopedInstances, synchronizedScope);
}
scopedInstances[0].lazySet(index, instance);
return instance;
}
8.AbstractUnsyncCompiledBinding类
这个类同样是实现CompiledBinding接口类的,这个类与AbstractCompiledBinding类似,所创建的属性和构造方法都与之相同:
protected final int scope;
protected final int index;
protected AbstractUnsyncCompiledBinding(int scope, int index) {
this.scope = scope;
this.index = index;
}
最大的不同就是实现getInstance的方法上。可以看到,这个类名中有Unsync,就说明它是非同步的。在创建实例上也是非同步的,在代码中我们可以看出:
public final R getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) {
AtomicReferenceArray array = scopedInstances[scope];
R instance = (R) array.get(index);
if (instance != null) return instance;
instance = doCreateInstance(scopedInstances, synchronizedScope);
array.lazySet(index, instance);
return instance;
}
大部分是与上面的相同,但是有一句array.lazySet(index, instance);可以看出,lazySet就是非同步的。
四 、总结
本次分析的代码是impl包中的8个类,这是这些类大都是和binding相关,并且大部分是为了实现不同的getInstance方法,getInstance方法在inject其他类中的应用还是很广泛的。