前言
implementation 'org.greenrobot:eventbus:3.0.0'
前面一章介绍了通过implementation 添加依赖的执行过程,在build 阶段的时候gradle 就会下载对应的额依赖。本章主要研究依赖的下载过程。
一 下载依赖
Configuration 有一个resolve 方法。
/**
* Resolves this configuration. This locates and downloads the files which make up this configuration, and returns
* the resulting set of files.
*
* @return The files of this configuration.
*/
Set<File> resolve();
有英文注释可以知道,这个方法会定位并且下载对应的文件。
public Set<File> resolve() {
return getFiles();
}
public Set<File> getFiles() {
return intrinsicFiles.getFiles();
}
其中的intrinsicFiles 为ConfigurationFileCollection,在DefaultConfiguration 的构造方法里面初始化的。
ConfigurationFileCollection.java
public Set<File> getFiles() {
ResolvedFilesCollectingVisitor visitor = new ResolvedFilesCollectingVisitor();
getSelectedArtifacts().visitArtifacts(visitor, lenient);
if (!lenient) {
rethrowFailure("files", visitor.getFailures());
}
return visitor.getFiles();
}
getSelectedArtifacts 主要是获取当前Configuration 需要依赖的项。
implementation 'org.greenrobot:eventbus:+'
如果我们使用上面的写法,也就是没有使用具体的版本号,此时getSelectedArtifacts也会访问网络获取的这个依赖的最新版本。
如果存在依赖冲突问题getSelectedArtifacts方法内部可能会抛出异常。
private SelectedArtifactSet getSelectedArtifacts() {
if (selectedArtifacts == null) {
assertResolvingAllowed();
resolveToStateOrLater(ARTIFACTS_RESOLVED);
selectedArtifacts = cachedResolverResults.getVisitedArtifacts().select(dependencySpec, viewAttributes, componentSpec, allowNoMatchingVariants);
}
return selectedArtifacts;
}
private void resolveToStateOrLater(InternalState requestedState) {
assertResolvingAllowed();
synchronized (resolutionLock) {
if (requestedState == GRAPH_RESOLVED || requestedState == ARTIFACTS_RESOLVED) {
//走这里
resolveGraphIfRequired(requestedState);
}
if (requestedState == ARTIFACTS_RESOLVED) {
resolveArtifactsIfRequired();
}
}
}
private void resolveGraphIfRequired(final InternalState requestedState) {
//代码有删减
resolver.resolveGraph(DefaultConfiguration.this, cachedResolverResults);
}
此处的resolver 是DefaultConfigurationResolver
public void resolveGraph(ConfigurationInternal configuration, ResolverResults results) {
//代码有删减
resolver.resolve(configuration, resolutionAwareRepositories, metadataHandler, Specs.<DependencyMetadata>satisfyAll(), graphVisitor, artifactsVisitor, attributesSchema, artifactTypeRegistry);
}
这个resolver 是 DefaultArtifactDependencyResolver
public void resolve(ResolveContext resolveContext, List<? extends ResolutionAwareRepository> repositories, GlobalDependencyResolutionRules metadataHandler, Spec<? super DependencyMetadata> edgeFilter, DependencyGraphVisitor graphVisitor, DependencyArtifactsVisitor artifactsVisitor, AttributesSchemaInternal consumerSchema, ArtifactTypeRegistry artifactTypeRegistry) {
LOGGER.debug("Resolving {}", resolveContext);
ComponentResolversChain resolvers = createResolvers(resolveContext, repositories, metadataHandler, artifactTypeRegistry);
DependencyGraphBuilder builder = createDependencyGraphBuilder(resolvers, resolveContext.getResolutionStrategy(), metadataHandler, edgeFilter, consumerSchema, moduleIdentifierFactory, moduleExclusions, buildOperationExecutor);
DependencyGraphVisitor artifactsGraphVisitor = new ResolvedArtifactsGraphVisitor(artifactsVisitor, resolvers.getArtifactSelector(), moduleExclusions);
// Resolve the dependency graph
builder.resolve(resolveContext, new CompositeDependencyGraphVisitor(graphVisitor, artifactsGraphVisitor));
}
assembleResult 内部会遍历所有需要下载的依赖然后执行visitEdges方法
ResolvedArtifactsGraphVisitor.java
@Override
public void visitEdges(DependencyGraphNode node) {
for (DependencyGraphEdge dependency : node.getIncomingEdges()) {
DependencyGraphNode parent = dependency.getFrom();
//这是关键
ArtifactsForNode artifacts = getArtifacts(dependency, node);
artifactResults.visitArtifacts(parent, node, artifacts.artifactSetId, artifacts.artifactSet);
}
for (LocalFileDependencyMetadata fileDependency : node.getOutgoingFileEdges()) {
int id = nextId++;
artifactResults.visitArtifacts(node, fileDependency, id, artifactSelector.resolveArtifacts(fileDependency));
}
}
exclusions 应该就是在implementation 方法传递的过滤规则,这里没去仔细看过。
DefaultArtifactSelector.java
RepositoryChainArtifactResolver chain 记录的是在setting.gradle 里面配置的所有仓库。
可以看到是先在缓存里面查询,缓存不存在就去远程获取。
sourceRepository.getRemoteAccess()用于获取访问网络访问器,resolveArtifacts(unpackedComponent, result)用于获取依赖。
这里以RemoteRepositoryAccess 为例。由名字就知道RemoteRepositoryAccess 可以获取远程数据。
@Override
public void resolveArtifact(ComponentArtifactMetadata artifact, ModuleSource moduleSource, BuildableArtifactResolveResult result) {
ExternalResourceResolver.this.resolveArtifact(artifact, moduleSource, result);
}
ExternalResourceResolver.java
protected void resolveArtifact(ComponentArtifactMetadata componentArtifact, ModuleSource moduleSource, BuildableArtifactResolveResult result) {
ModuleComponentArtifactMetadata artifact = (ModuleComponentArtifactMetadata) componentArtifact;
File localFile;
try {
localFile = download(artifact, moduleSource, result);
} catch (Throwable e) {
result.failed(new ArtifactResolveException(artifact.getId(), e));
return;
}
if (localFile != null) {
result.resolved(localFile);
} else {
result.notFound(artifact.getId());
}
}
protected File download(ModuleComponentArtifactMetadata artifact, ModuleSource moduleSource, BuildableArtifactResolveResult result) {
LocallyAvailableExternalResource artifactResource = createArtifactResolver(moduleSource).resolveArtifact(artifact, result);
if (artifactResource == null) {
return null;
}
return artifactResource.getFile();
}
createArtifactResolver 返回的是DefaultExternalResourceArtifactResolver
public LocallyAvailableExternalResource resolveArtifact(ModuleComponentArtifactMetadata artifact, ResourceAwareResolveResult result) {
if (artifact instanceof ModuleDescriptorArtifactMetadata) {
return downloadStaticResource(ivyPatterns, artifact, result);
}
return downloadStaticResource(artifactPatterns, artifact, result);
}
private LocallyAvailableExternalResource downloadStaticResource(List<ResourcePattern> patternList, final ModuleComponentArtifactMetadata artifact, ResourceAwareResolveResult result) {
for (ResourcePattern resourcePattern : patternList) {
//获取需要下载的依赖
ExternalResourceName location = resourcePattern.getLocation(artifact);
result.attempted(location);
LOGGER.debug("Loading {}", location);
LocallyAvailableResourceCandidates localCandidates = locallyAvailableResourceFinder.findCandidates(artifact);
try {
LocallyAvailableExternalResource resource = resourceAccessor.getResource(location, new CacheAwareExternalResourceAccessor.ResourceFileStore() {
public LocallyAvailableResource moveIntoCache(File downloadedResource) {
return fileStore.move(artifact.getId(), downloadedResource);
}
}, localCandidates);
if (resource != null) {
return resource;
}
} catch (Exception e) {
throw ResourceExceptions.getFailed(location.getUri(), e);
}
}
return null;
}
ExternalResourceName location 表示需要下载的来,resourceAccessor是CacheAwareExternalResourceAccessor,有名字可以直到,resourceAccessor会优先在缓存里面查找对应的依赖。如果缓存里面不存在,那么会DefaultExternalResourceRepository 的resource 方法下载资源。最终通过AccessorBackedExternalResource 的withContentIfPresent下载对应的依赖。
private LocallyAvailableExternalResource copyToCache(final ExternalResourceName source, final ResourceFileStore fileStore, final ExternalResource resource) {
// Download to temporary location
DownloadAction downloadAction = new DownloadAction(source);
try {
//resource 是AccessorBackedExternalResource 的代理类
resource.withContentIfPresent(downloadAction);
} catch (Exception e) {
throw ResourceExceptions.getFailed(source.getUri(), e);
}
if (downloadAction.metaData == null) {
return null;
}
// Move into cache
try {
return moveIntoCache(source, downloadAction.destination, fileStore, downloadAction.metaData);
} finally {
downloadAction.destination.delete();
}
}
@Nullable
@Override
public <T> ExternalResourceReadResult<T> withContentIfPresent(Transformer<? extends T, ? super InputStream> transformer) throws ResourceException {
try {
//accessor
ExternalResourceReadResponse response = accessor.openResource(name.getUri(), revalidate);
if (response == null) {
return null;
}
try {
CountingInputStream input = new CountingInputStream(new BufferedInputStream(response.openStream()));
try {
T value = transformer.transform(input);
return ExternalResourceReadResult.of(input.getCount(), value);
} finally {
input.close();
}
} finally {
response.close();
}
} catch (IOException e) {
throw ResourceExceptions.getFailed(name.getUri(), e);
}
}
accessor 为HttpResourceAccessor,此时通过HttpResourceAccessor 打开网络连接,获取的输入流。
@Override
@Nullable
public HttpResponseResource openResource(final URI uri, boolean revalidate) {
String location = uri.toString();
LOGGER.debug("Constructing external resource: {}", location);
HttpClientResponse response = http.performGet(location, revalidate);
if (response != null) {
return wrapResponse(uri, response);
}
return null;
}
http 为HttpClientHelper,HttpClientHelper 内部通过HttpClient 访问网络,关于Gradle 访问网络这一块就接收到这。
二、产物
前面介绍了Gradle 下载依赖的过程,可以知道Gradle 最终使用的是HttpClinet 网络框架下载的依赖文件,但是依赖文件下载之后还并不可以直接使用,例如 implementation ‘org.greenrobot:eventbus:3.0.0’ 下载下来是个aar文件,但android 最终需要的是包含源码的jar 文件,因此这里就需要解压等操作。这一步的操作名为Transform ,经过Transform 之后的文件我们称之为产物,也是我们最终最终依赖的文件。
public Set<File> getFiles() {
ResolvedFilesCollectingVisitor visitor = new ResolvedFilesCollectingVisitor();
getSelectedArtifacts().visitArtifacts(visitor, lenient);
if (!lenient) {
rethrowFailure("files", visitor.getFailures());
}
return visitor.getFiles();
}
private SelectedArtifactSet getSelectedArtifacts() {
if (selectedArtifacts == null) {
assertResolvingAllowed();
resolveToStateOrLater(ARTIFACTS_RESOLVED);
selectedArtifacts = cachedResolverResults.getVisitedArtifacts().select(dependencySpec, viewAttributes, componentSpec, allowNoMatchingVariants);
}
return selectedArtifacts;
}
private void resolveToStateOrLater(InternalState requestedState) {
assertResolvingAllowed();
synchronized (resolutionLock) {
if (requestedState == GRAPH_RESOLVED || requestedState == ARTIFACTS_RESOLVED) {
resolveGraphIfRequired(requestedState);
}
if (requestedState == ARTIFACTS_RESOLVED) {
resolveArtifactsIfRequired();
}
}
}
resolveGraphIfRequired 是下载对应的依赖,这个在前面介绍了,resolveArtifactsIfRequired 会遍历下载的依赖文件然后进行转换。
private void resolveArtifactsIfRequired() {
if (resolvedState == ARTIFACTS_RESOLVED) {
return;
}
if (resolvedState != GRAPH_RESOLVED) {
throw new IllegalStateException("Cannot resolve artifacts before graph has been resolved.");
}
resolver.resolveArtifacts(DefaultConfiguration.this, cachedResolverResults);
resolvedState = ARTIFACTS_RESOLVED;
}
public void resolveArtifacts(ConfigurationInternal configuration, ResolverResults results) {
ArtifactResolveState resolveState = (ArtifactResolveState) results.getArtifactResolveState();
ResolvedGraphResults graphResults = resolveState.graphResults;
VisitedArtifactsResults artifactResults = resolveState.artifactsResults;
TransientConfigurationResultsBuilder transientConfigurationResultsBuilder = resolveState.transientConfigurationResultsBuilder;
TransientConfigurationResultsLoader transientConfigurationResultsFactory = new TransientConfigurationResultsLoader(transientConfigurationResultsBuilder, graphResults);
DefaultLenientConfiguration result = new DefaultLenientConfiguration(configuration, resolveState.failures, artifactResults, resolveState.fileDependencyResults, transientConfigurationResultsFactory, artifactTransforms, buildOperationExecutor);
results.artifactsResolved(new DefaultResolvedConfiguration(result), result);
}
results 与下面截图中的cachedResolverResults是同一个对象。
results.artifactsResolved 仅仅是保存一些变量。
@Override
public void artifactsResolved(ResolvedConfiguration resolvedConfiguration, VisitedArtifactSet visitedArtifacts) {
this.resolvedConfiguration = resolvedConfiguration;
this.visitedArtifacts = visitedArtifacts;
this.artifactResolveState = null;
}
此处需要知道的是VisitedArtifactSet visitedArtifacts实际是DefaultLenientConfiguration
在调用完resolveToStateOrLater之后会接着调用cachedResolverResults.getVisitedArtifacts().select 方法。其中cachedResolverResults.getVisitedArtifacts() 返回的就是上面创建的DefaultLenientConfiguration 对象。
下面接着看DefaultLenientConfiguration 的select 方法
@Override
public SelectedArtifactSet select(final Spec<? super Dependency> dependencySpec, final AttributeContainerInternal requestedAttributes, final Spec<? super ComponentIdentifier> componentSpec, boolean allowNoMatchingVariants) {
final SelectedArtifactResults artifactResults;
//
VariantSelector selector = artifactTransforms.variantSelector(requestedAttributes, allowNoMatchingVariants);
artifactResults = this.artifactResults.select(componentSpec, selector);
return new SelectedArtifactSet() {//代码有删减};
}
这里面的artifactTransforms 用来产物转换,例如android插件内的AarTransform.
这个值是在构造DefaultConfigurationResolver确定的。其实际类型是DefaultArtifactTransforms。
artifactTransforms.variantSelector 返回AttributeMatchingVariantSelector 类型的一个变量,而this.artifactResults.select(componentSpec, selector)内部会调用AttributeMatchingVariantSelector 的select方法。
@Override
public ResolvedArtifactSet select(ResolvedVariantSet producer) {
try {
return doSelect(producer);
} catch (Throwable t) {
return new BrokenResolvedArtifactSet(t);
}
}
private ResolvedArtifactSet doSelect(ResolvedVariantSet producer) {
AttributeMatcher matcher = schema.withProducer(producer.getSchema());
List<? extends ResolvedVariant> matches = matcher.matches(producer.getVariants(), requested);
List<Pair<ResolvedVariant, ConsumerVariantMatchResult.ConsumerVariant>> candidates = new ArrayList<Pair<ResolvedVariant, ConsumerVariantMatchResult.ConsumerVariant>>();
for (ResolvedVariant variant : producer.getVariants()) {
AttributeContainerInternal variantAttributes = variant.getAttributes().asImmutable();
ConsumerVariantMatchResult matchResult = new ConsumerVariantMatchResult();
//这个是核心
matchingCache.collectConsumerVariants(variantAttributes, requested, matchResult);
for (ConsumerVariantMatchResult.ConsumerVariant consumerVariant : matchResult.getMatches()) {
candidates.add(Pair.of(variant, consumerVariant));
}
}
if (candidates.size() == 1) {
Pair<ResolvedVariant, ConsumerVariantMatchResult.ConsumerVariant> result = candidates.get(0);
return new ConsumerProvidedResolvedVariant(result.getLeft().getArtifacts(), result.getRight().attributes, result.getRight().transformer);
}
}
}
我们接着进入VariantAttributeMatchingCache 的collectConsumerVariants 方法
public void collectConsumerVariants(AttributeContainerInternal actual, AttributeContainerInternal requested, ConsumerVariantMatchResult result) {
AttributeSpecificCache toCache = getCache(requested);
ConsumerVariantMatchResult cachedResult = toCache.transforms.get(actual);
if (cachedResult == null) {
cachedResult = new ConsumerVariantMatchResult();
findProducersFor(actual, requested, cachedResult);
toCache.transforms.put(actual, cachedResult);
}
cachedResult.applyTo(result);
}
variantTransforms 里面保存的应该就是用户注册的转换器。
inputVariant.transformer.transform(file) 就会执行用户注册的转换器。下面我们以android 的ExtractAarTransform为例,ExtractAarTransform 主要是解压aar文件。
override fun transform(outputs: TransformOutputs) {
recordArtifactTransformSpan(
parameters.projectName.get(),
GradleTransformExecutionType.EXTRACT_AAR_ARTIFACT_TRANSFORM
) {
val inputFile = primaryInput.get().asFile
val name = Files.getNameWithoutExtension(inputFile.name)
val outputDir = outputs.dir(name)
FileUtils.mkdirs(outputDir)
val aarExtractor = AarExtractor()
aarExtractor.extract(inputFile, outputDir)
val classesJar = File(File(outputDir, FD_JARS), FN_CLASSES_JAR)
if (!classesJar.exists()) {
try {
Files.createParentDirs(classesJar)
FileOutputStream(classesJar).use { out ->
// FileOutputStream above is the actual OS resource that will get closed,
// JarOutputStream writes the bytes or an empty jar in it.
val jarOutputStream = JarOutputStream(BufferedOutputStream(out), Manifest())
jarOutputStream.close()
}
} catch (e: IOException) {
throw RuntimeException("Cannot create missing classes.jar", e)
}
}
}
}
AarExtractor 的extract 方法会将aar 文件解压到指定的文件夹。android 插件里面还有一个AarTransform ,有感兴趣的可以自己看看。
总结
本文的内容到此就结束了,本篇主要粗略的介绍了一下Gradle 是如何下载依赖文件以及下载之后的转换操作,其实这对于我们的实际开发没什么作用,当初之所以看这一块主要是我想看看Gradle 是使用的什么网络框架。