---
深入理解 Gradle 框架之 依赖实现分析
---

> 本文摘自：@ AllenWang [深入理解gradle框架之二：依赖实现分析](https://mp.weixin.qq.com/s/WQCqUaYDPHDIjUHlxjRIkw)

### 目录

1. 引言
2. 从 implementation 说起

### 引言

大家在日常开发中，见过最多的可能就是下面三种依赖声明：

```groovy
implementation “org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version”
implementation project(":applemodule")
implementation fileTree(dir:‘libs’, include:[’*.jar’])
```

这些不同的依赖声明，内部实现机制是怎么样的？

### 从 implementation 说起

```
implementation 'com.android.support:appcompat-v7:28.0.0'
```

按照 Groovy 的语法，这里要执行的是 DependencyHandler 的 implementation() 方法，参数为 'com.android.support:appcompat-v7:28.0.0'。

但是在 DependencyHandler 中并没有 implementation() 这个方法，这是怎么回事呢？

```java
public interface DependencyHandler {

    Dependency add(String configurationName, Object dependencyNotation);
    
    Dependency create(Object dependencyNotation);
    
    Dependency module(Object notation);
    
    Dependency project(Map<String, ?> notation);
    
    Dependency gradleApi();
    
    Dependency localGroovy();
    
    //...
}
```

#### MethodMissing

这其实涉及到了 Groovy 语言的一个重要特性：methodMissing，这个特性允许在运行时 catch 对于未定义方法的调用。

Gradle 对这个特性进行封装，一个类要想使用这个特性，只要实现 MixIn 接口即可，这个接口如下：

```java
public interface MethodMixIn {
    MethodAccess getAdditionalMethods();
}
```

其中 MethodAccess 接口如下：

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

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

也就是说，对于 DependencyHandler 中未定义的方法（如 implementation() 方法），只要 hasMethod 返回 true，就会调用到 MethodAccess 的实现者的 tryInvokeMethod 方法，其中 name 为 configuration 名称，arguments 就是  'com.android.support:appcompat-v7:28.0.0' 这个参数。

那 DependencyHandler 接口的实现者 DefaultDependencyHandler 是如何实现 MethodMixIn 这个接口的呢？

```java
    public MethodAccess getAdditionalMethods() {
        return this.dynamicMethods;
    }
```

这个 dynamicMethods 类型为 DynamicAddDependencyMethods，源码如下：

```java
class DynamicAddDependencyMethods implements MethodAccess {
    private ConfigurationContainer configurationContainer;
    private DynamicAddDependencyMethods.DependencyAdder dependencyAdder;

    DynamicAddDependencyMethods(ConfigurationContainer configurationContainer, DynamicAddDependencyMethods.DependencyAdder dependencyAdder) {
        this.configurationContainer = configurationContainer;
        this.dependencyAdder = dependencyAdder;
    }

    public boolean hasMethod(String name, Object... arguments) {
        return arguments.length != 0 && this.configurationContainer.findByName(name) != null;
    }

    public DynamicInvokeResult tryInvokeMethod(String name, Object... arguments) {
        if (arguments.length == 0) {
            return DynamicInvokeResult.notFound();
        } else {
            Configuration configuration = (Configuration)this.configurationContainer.findByName(name);
            if (configuration == null) {
                return DynamicInvokeResult.notFound();
            } else {
                List<?> normalizedArgs = CollectionUtils.flattenCollections(arguments);
                if (normalizedArgs.size() == 2 && normalizedArgs.get(1) instanceof Closure) {
                    return DynamicInvokeResult.found(this.dependencyAdder.add(configuration, normalizedArgs.get(0), (Closure)normalizedArgs.get(1)));
                } else if (normalizedArgs.size() == 1) {
                    return DynamicInvokeResult.found(this.dependencyAdder.add(configuration, normalizedArgs.get(0), (Closure)null));
                } else {
                    Iterator var5 = normalizedArgs.iterator();

                    while(var5.hasNext()) {
                        Object arg = var5.next();
                        this.dependencyAdder.add(configuration, arg, (Closure)null);
                    }

                    return DynamicInvokeResult.found();
                }
            }
        }
    }

    interface DependencyAdder<T> {
        T add(Configuration var1, Object var2, Closure var3);
    }
}
```

注意到它是实现了 MethodAccess 这个接口的，首先看它的 hasMethod() 方法，很简单，返回 true 的条件是：

* 参数长度不为零
* configuration 必须是已经定义过的

然后再看 tryInvokeMethod()，它会先通过 configurationsContainer 找到对应的 configuration，然后分如下几种情况：

* 参数个数为 2，并且第 2 个参数是 Closure
* 参数个数为 1
* 其他情形

不过不管哪种情形，都会先调用 dependencyAdder 的 add() 方法，而 dependencyAdder 是 DefaultDependencyHandler.DirectDependencyAdder 对象，其 add() 方法如下：

```java
public Dependency add(Configuration configuration, Object dependencyNotation, @Nullable Closure configureAction) {
            return DefaultDependencyHandler.this.doAdd(configuration, dependencyNotation, configureAction);
        }
```

可见，其实是调用外部类 DefaultDependencyHandler 的 doAdd() 方法，在下一小节分析该方法。

#### DefaultDependencyHandler.doAdd() 方法分析

```java
    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;
        }
    }
```

可见，这里会先判断 dependencyNotation 是否为 Configuration，如果是的话，就让当前的 configuration 继承自 other 这个 configuration，而继承的意思就是，后续所有添加到 other 的依赖，也会添加到当前这个 configuration 中。

为什么还要考虑参数中的 dependecnyNotation 是否为 Configuration 的情形呢？

其实就是考虑到有诸如 implementation project(path: ':appmodule', configuration: 'configA') 这样的依赖声明。

至于依赖的创建过程，在下一节进行分析。

### 依赖创建过程分析

DefaultDependencyHandler 的 create() 方法如下：

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

其中的 dependencyFactory 为 DefaultDependencyFactory 对象，其 createDependency() 方法如下：

```java
    public Dependency createDependency(Object dependencyNotation) {
        Dependency dependency = (Dependency)this.dependencyNotationParser.parseNotation(dependencyNotation);
        this.injectAttributesFactory(dependency);
        return dependency;
    }
```

可见，它是直接调用 dependencyNotationParser 这个解析器对于 denpendencyNotation 进行解析。

其中的 dependencyNotationParser 是实现了接口 NotationParser\<Object, Dependency> 接口的对象。

为了找出这里的 dependencyNotationParser 到底是哪个类的实例，查看 DefaultDependencyFactory 的创建，在 DependencyManagementBuildScopeServices 类中，如下：

```java
    DependencyFactory createDependencyFactory(Instantiator instantiator, ProjectAccessListener projectAccessListener, StartParameter startParameter, ClassPathRegistry classPathRegistry, CurrentGradleInstallation currentGradleInstallation, FileLookup fileLookup, RuntimeShadedJarFactory runtimeShadedJarFactory, ImmutableAttributesFactory attributesFactory, SimpleMapInterner stringInterner) {
        DefaultProjectDependencyFactory factory = new DefaultProjectDependencyFactory(projectAccessListener, instantiator, startParameter.isBuildProjectDependencies());
        ProjectDependencyFactory projectDependencyFactory = new ProjectDependencyFactory(factory);
        return new DefaultDependencyFactory(DependencyNotationParser.parser(instantiator, factory, classPathRegistry, fileLookup, runtimeShadedJarFactory, currentGradleInstallation, stringInterner), DependencyConstraintNotationParser.parser(instantiator, stringInterner), (new ClientModuleNotationParserFactory(instantiator, stringInterner)).create(), projectDependencyFactory, attributesFactory);
    }
```

可见，它是通过 DependencyNotationParser.parser() 方法创建的，该方法如下：

```java
    public static NotationParser<Object, Dependency> parser(Instantiator instantiator, DefaultProjectDependencyFactory dependencyFactory, ClassPathRegistry classPathRegistry, FileLookup fileLookup, RuntimeShadedJarFactory runtimeShadedJarFactory, CurrentGradleInstallation currentGradleInstallation, Interner<String> stringInterner) {
        return NotationParserBuilder.toType(Dependency.class).fromCharSequence(new DependencyStringNotationConverter(instantiator, DefaultExternalModuleDependency.class, stringInterner)).converter(new DependencyMapNotationConverter(instantiator, DefaultExternalModuleDependency.class)).fromType(FileCollection.class, new DependencyFilesNotationConverter(instantiator)).fromType(Project.class, new DependencyProjectNotationConverter(dependencyFactory)).fromType(ClassPathNotation.class, new DependencyClassPathNotationConverter(instantiator, classPathRegistry, fileLookup.getFileResolver(), runtimeShadedJarFactory, currentGradleInstallation)).invalidNotationMessage("Comprehensive documentation on dependency notations is available in DSL reference for DependencyHandler type.").toComposite();
    }
```

这个方法其实很好理解，它其实是创建了多个实现了接口 NotationConverter 的对象，然后将这些转换器都添加在一起，构成一个综合的转换器。

其中，DependencyStringNotationConvert 负责将字符串类型的 notation 转换为 DefaultExternalModuleDependency，也就是对应 implementation 'com.android.support:appcompat-v7:25.1.0' 这样的声明；

DependencyFilesNotationConverter 将 FileCollection 转换为 SelfResolvingDependency，也就是对应的 implementation fileTree(dir: 'libs', include:['*.jar']) 这样的声明；

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

DependencyClasspathNotationConvert 将 ClasspathNotation 转换为 SelfResolvingDependency；

到这里，就知道类似 implementation 'com.android.support:appcompat-v7:28.0.0' 和 implementation project 这样的声明，其实是被不同的转换器，转换成了 SelfResolvingDependency 或者 ProjectDependency。

这里可以看出，除了 project 依赖之外，其他都转换成 SelfResolvingDependency，所谓的 SelfResolvingDependency 其实是可以自解析的依赖，独立于 repository。

ProjectDependency 则不然，它是依赖于 repository 的，下面就分析 ProjectDependency 的独特之处。

