ActiveJ学习心得——inject(2)

2021SC@SDUSC

一、代码分析内容

本次代码分析依然是分析ActiveJ源代码的inject注入部分,下面一个例子就是使用inject的一个实例:

class Main extends Launcher {
    
    
  @Inject
  String message;
  
  @Provides
  String message() {
    
    
    return "你好,世界";
  }
  
  @Override
  protected void run() {
    
    
    System.out.println(message);
  }
  
  public static void main(String[] args) throws Exception {
    
    
    Launcher launcher = new Main();
    launcher.launch(args);
  }
}

上一个博客我介绍了Inject、InstanceInjector、InstanceProvider、Key、KeyPattern、Qualifiers、ResourceLocator、Scope这8个单独的类的各个功能,这个博客分析core-inject包中binding包的功能。

二、Binding综述

绑定是ActiveJ Inject的主要组件之一。
它可以归结为“内省函数”,因为它只描述了从对象数组及其Dependency的依赖数组中创建T实例的函数。
它还包含一组io.activej.inject.module.AbstractModule绑定类DSL 、静态工厂方法以及一些函数转换,以便于创建不可变的绑定修改。
应用程序组件可能需要一些依赖性才能被创建,依赖性注入负责为应用程序组件提供这些所需的对象。为了做到这一点,我们需要指定 ,它需要提供什么 ,以及如何使用提供的对象。
因此绑定有两个相应的属性。
一组需要创建的Set依赖关系(POJO与 Key)。
BindingCompiler将编译所需的实例

 public final class Binding<T> {
    
    
     final Set<Dependency> dependencies;
     final BindingCompiler<T> compiler;
}

Binding 就像一个 “配方”,说明如何创建一个组件的实例。
Dependency——显示应该使用什么成分。
Compiler——知道如何把它们放在一起进行操作。

三、binding包结构

在这里插入图片描述

binding包中有8个类和3个接口,Binding类是其他几个类的前提,Binding类中定义了一些属性和方法是在其他类和接口中需要用到的。

四、代码解读

1.Binding类
绑定是ActiveJ Inject的主要组件之一。
它可以归结为“内省函数”,因为它只描述了从对象数组及其Dependency的依赖数组中创建T实例的函数。
Binding类中定义的对象如下:

	private final Set<Dependency> dependencies;
	private BindingType type;

	private @Nullable LocationInfo location;

构造方法如下:

	protected Binding(@NotNull Set<Dependency> dependencies) {
    
    
		this(dependencies, BindingType.REGULAR, null);
	}

	protected Binding(@NotNull Set<Dependency> dependencies, BindingType type, @Nullable LocationInfo location) {
    
    
		this.dependencies = dependencies;
		this.type = type;
		this.location = location;
	}

2.BindingGenerator接口
这是一个函数,当Injector编译最终绑定图trie时,它可以尝试生成缺少的依赖项绑定。
此类函数的一个示例可以是io.activej.inject.util.ReflectionUtils#generateImplicitBinding the injection DSL。

@FunctionalInterface
public interface BindingGenerator<T> {
    
    
	@Nullable Binding<T> generate(BindingLocator bindings, Scope[] scope, Key<T> key);
}

3.BindingGenerators类
BindingGenerators是从不生成任何内容的默认生成器。
模块导出具有原始类键的绑定生成器的多重映射。
此生成器将此类映射聚合为一个大型生成器,供Injector#compile方法使用。
对于每个请求的key,根据其原始类获取一组生成器。
然后调用此集合中的所有生成器,如果其中一个且只有一个生成了绑定,则返回此绑定。
当没有生成绑定时,组合生成器也不生成绑定,当多个绑定生成时,这被认为是一个错误。
当请求键的原始类是一个接口时,它由相等匹配,当它是某个类时,将调用其最近超类的生成器。
在为某些具体类创建生成器时要注意这一点:它们通常是为接口或最终类创建的。

public static BindingGenerator<?> combinedGenerator(Map<KeyPattern<?>, Set<BindingGenerator<?>>> generators) {
    
    
		LinkedHashMap<KeyPattern<?>, Set<BindingGenerator<?>>> sorted = sortPatternsMap(generators);
		return (bindings, scope, key) -> {
    
    
			for (Map.Entry<KeyPattern<?>, Set<BindingGenerator<?>>> entry : sorted.entrySet()) {
    
    
				if (entry.getKey().match(key)) {
    
    
					for (BindingGenerator<?> generator : entry.getValue()) {
    
    
						@Nullable Binding<Object> generated = ((BindingGenerator<Object>) generator).generate(bindings, scope, key);
						if (generated != null) return generated;
					}
				}
			}
			return null;
		};
	}

四、BindingToKey类
BindingToKey类继承Binding类,这个类是与key进行绑定的类。

BindingToKey(Key<? extends T> key) {
    
    
		super(Collections.singleton(Dependency.toKey(key)));
		this.key = key;
	}

	public Key<? extends T> getKey() {
    
    
		return key;
	}

	@Override
	public CompiledBinding<T> compile(CompiledBindingLocator compiledBindings, boolean threadsafe, int scope, @Nullable Integer slot) {
    
    
		//noinspection unchecked
		return (CompiledBinding<T>) compiledBindings.get(key);
	}

五、BindingTransformer接口
这是一个转换函数,Injector对每个绑定应用一次。

@FunctionalInterface
public interface BindingTransformer<T> {
    
    
	@NotNull Binding<T> transform(BindingLocator bindings, Scope[] scope, Key<T> key, Binding<T> binding);
}

六、BindingTransformers类
此转换器将此类映射聚合到一个大型生成器中,供Injector#compile方法使用。映射将转换为已排序的集合列表。然后,对于这些集合中的每一个,类似于bindingGenerator#combinedGenerator生成器,只允许该集合中的零个或一个转换器返回它所给出的绑定以外的任何内容(作为标识转换器)。
因此,如果两个转换器的优先级不同,那么它们可以按照优先级顺序应用。

public static BindingTransformer<?> combinedTransformer(Map<KeyPattern<?>, Set<BindingTransformer<?>>> transformers) {
    
    
		LinkedHashMap<KeyPattern<?>, Set<BindingTransformer<?>>> sorted = sortPatternsMap(transformers);
		return (bindings, scope, key, binding) -> {
    
    
			Binding<Object> result = binding;
			for (Map.Entry<KeyPattern<?>, Set<BindingTransformer<?>>> entry : sorted.entrySet()) {
    
    
				if (entry.getKey().match(key)) {
    
    
					for (BindingTransformer<?> transformer : entry.getValue()) {
    
    
						result = ((BindingTransformer<Object>) transformer).transform(bindings, scope, key, result);
					}
				}
			}
			return result;
		};
	}

六、Dependency类
一个简单的POJO,它将Key与布尔值结合起来,布尔值指示在何处需要一个键以及它是否是隐式的。
下面是Dependency定义的属性和构造方法:

private final Key<?> key;
	private final boolean required;
	private final boolean implicit;

	public Dependency(Key<?> key, boolean required, boolean implicit) {
    
    
		this.key = key;
		this.required = required;
		this.implicit = implicit;
	}

隐式依赖项不会导致循环检查错误,并且在调试图形viz输出中以灰色绘制。此类依赖项不应实例化,因为它们可能会导致各种与周期相关的错误,
这样的无限递归。
它们用于描述某些逻辑依赖关系,这些逻辑依赖关系可能是循环的,也可能不是循环的。

	public static Dependency implicit(Key<?> key, boolean required) {
    
    
		return new Dependency(key, required, true);
	}

	public Key<?> getKey() {
    
    
		return key;
	}

	public boolean isRequired() {
    
    
		return required;
	}

	public boolean isImplicit() {
    
    
		return implicit;
	}

	@Override
	public boolean equals(Object o) {
    
    
		if (this == o) {
    
    
			return true;
		}
		if (o == null || getClass() != o.getClass()) {
    
    
			return false;
		}

		Dependency that = (Dependency) o;

		return required == that.required && Objects.equals(key, that.key);
	}

五、总结

本次解读的代码是binding包中的类或接口,有些是其他类的依赖,有些是需要在其他类中实现的接口,都是比较重要的。

猜你喜欢

转载自blog.csdn.net/zth_idea/article/details/120765091