ActiveJ学习心得——inject(6)

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其他类中的应用还是很广泛的。

Guess you like

Origin blog.csdn.net/zth_idea/article/details/121224026