gradle源码分析之implementation依赖

Groovy

dependencies {
    implementation project(':sdk')
}

groovy会做两步:

  • 解析project
  • 解析implementation

我们先看第二步

解析implementation

Project.java

/**
 * 

Configures the dependencies for this project. * *

This method executes the given closure against the {@link DependencyHandler} for this project. The {@link * DependencyHandler} is passed to the closure as the closure's delegate. * *

Examples:

* See docs for {@link DependencyHandler} * * @param configureClosure the closure to use to configure the dependencies. */ void dependencies(Closure configureClosure); public void dependencies(Closure configureClosure) { ConfigureUtil.configure(configureClosure, this.getDependencies()); }

dependenciesproject下的方法, 实际返回DefaultDependencyHandler.

即执行DefaultDependencyHandlerimplementation方法。

但是底下并没有这个方法,

MethodMissing

MethodMixIn

public interface MethodMixIn {
    MethodAccess getAdditionalMethods();
}

this.dynamicMethods = new DynamicAddDependencyMethods(configurationContainer, new DefaultDependencyHandler.DirectDependencyAdder());

MethodAccess

public interface MethodAccess {
    boolean hasMethod(String var1, Object... var2);

    DynamicInvokeResult tryInvokeMethod(String var1, Object... var2);
}

动态语言常见的methodMissing功能,这里在tryInvokeMethod尝试解析方法与参数。

class DynamicAddDependencyMethods implements MethodAccess {

    //name = "implementation" argument: project(sdk)
    public DynamicInvokeResult tryInvokeMethod(String name, Object... arguments) {
        //找是否有对应的configurationName
        Configuration configuration = (Configuration)this.configurationContainer.findByName(name);
        
        return DynamicInvokeResult.found(this.dependencyAdder.add(configuration, normalizedArgs.get(0), (Closure)null));
    }
}
/**
 dependencyNotation: project(:xxx)
*/
private Dependency doAdd(Configuration configuration, Object dependencyNotation, Closure configureClosure) {
    if (dependencyNotation instanceof Configuration) {
        Configuration other = (Configuration)dependencyNotation;
        if (!this.configurationContainer.contains(other)) {
            throw new UnsupportedOperationException("Currently you can only declare dependencies on configurations from the same project.");
        } else {
            configuration.extendsFrom(new Configuration[]{other});
            return null;
        }
    } else {
        Dependency dependency = this.create(dependencyNotation, configureClosure);
        configuration.getDependencies().add(dependency);
        return dependency;
    }
}

public Dependency create(Object dependencyNotation, Closure configureClosure) {
    Dependency dependency = this.dependencyFactory.createDependency(dependencyNotation);
    return (Dependency)ConfigureUtil.configure(configureClosure, dependency);
}

//DependencyProjectNotationConverter
public Dependency createDependency(Object dependencyNotation) {
    Dependency dependency = (Dependency)this.dependencyNotationParser.parseNotation(dependencyNotation);
    this.injectServices(dependency);
    return dependency; //DefaultProjectDependency
}

DependencyProjectNotationConverter 将 Project 转换为 ProjectDependency,对应 implementation project(":applemodule") 这样的情形

所以主要就两步:

1. Dependency dependency = this.create(dependencyNotation, configureClosure);
2. configuration.getDependencies().add(dependency);

解析project

一样进入tryInvokeMethod,但是:

Configuration configuration = (Configuration)this.configurationContainer.findByName(name);

DynamicAddDependencyMethods是没有projectconfiguration:

于是进入DefaultProjectproject方法

public class DefaultProject {
    
    public ProjectInternal project(String path) {
        ProjectInternal project = this.findProject(path);
        if (project == null) {
            throw new UnknownProjectException(String.format("Project with path '%s' could not be found in %s.", path, this));
        } else {
            return project;
        }
    }
}

问题

为什么能进入DefaultProjectproject方法? 因为回到parent去解析?

ktx

dependencies {
    implementation(project(":sdkapi"))
}

ProjectExtensions.kt

fun Project.dependencies(configuration: DependencyHandlerScope.() -> Unit) =
    DependencyHandlerScope.of(dependencies).configuration()
    
companion object {
    fun of(dependencies: DependencyHandler): DependencyHandlerScope =
        DependencyHandlerScope(dependencies)
}

解析project

DependencyHandlerExtensions.kt

fun DependencyHandler.project(
    path: String,
    configuration: String? = null
): ProjectDependency =

    uncheckedCast(
        project(
            if (configuration != null) mapOf("path" to path, "configuration" to configuration)
            else mapOf("path" to path)))

override fun project(notation: Map): Dependency =
    delegate.project(notation)

最后走到DependencyHandler.project(map)方法 -> (delegate)

public Dependency project(Map notation) {
    return this.dependencyFactory.createProjectDependencyFromMap(this.projectFinder, notation);
}

怪不得一直不知道这个方法是用来干啥的

project(map)
public ProjectDependency createFromMap(ProjectFinder projectFinder, Map map) {
    return (ProjectDependency)NotationParserBuilder.toType(ProjectDependency.class).converter(new ProjectDependencyFactory.ProjectDependencyMapNotationConverter(projectFinder, this.factory)).toComposite().parseNotation(map);
}

最后其实就是进入:

DefaultProjectDependencyFactory

public ProjectDependency create(ProjectInternal project, String configuration) {
    DefaultProjectDependency projectDependency = (DefaultProjectDependency)this.instantiator.newInstance(DefaultProjectDependency.class, new Object[]{project, configuration, this.projectAccessListener, this.buildProjectDependencies});
    projectDependency.setAttributesFactory(this.attributesFactory);
    projectDependency.setCapabilityNotationParser(this.capabilityNotationParser);
    return projectDependency;
}

先通过 projectFinder 找到相应的 Project,然后通过 factory 创建 ProjectDependency

解析implementation

val implementation by configurations

operator fun Configuration.invoke(dependencyNotation: Any): Dependency? =
    add(name, dependencyNotation)

DefaultDependencyHandler.java

public Dependency add(String configurationName, Object dependencyNotation) {
    return this.add(configurationName, dependencyNotation, (Closure)null);
}

问题

val implementation by configurations咋实现的,还没看懂

参考资料

https://henleylee.github.io/posts/2019/5fe63be9.html#toc-heading-5
https://www.jianshu.com/p/0e04186a6aca

你可能感兴趣的:(gradle源码分析之implementation依赖)