Gradle源碼解讀(二)

  • 概述

    之前分析了從執(zhí)行 gradlew assemble 命令開始,gradle是如何一步步執(zhí)行起來的塘揣,上文說到最后會執(zhí)行this.executer.execute方法征峦,這一篇我就從這里開始繼續(xù)往下走,順便看一下this.executer的創(chuàng)造方法。

    在追溯this.executer是什么的過程中發(fā)現(xiàn)了一種很巧妙的構(gòu)造模式滴须,因為它是提供某種類型實例的創(chuàng)建,所以我把它叫做工廠模式叽奥,但是和傳統(tǒng)的工廠模式相比又有特別的地方扔水,我不知道該怎么命名它,它是通過注冊方法的反射調(diào)用來創(chuàng)建對應類型的實例的朝氓,暫且就叫它方法工廠模式吧魔市。

    在傳統(tǒng)的工廠模式應用中,我們通常會創(chuàng)建一個工廠類赵哲,然后通過某個getInstance方法來創(chuàng)建對應實例待德,而這個升級版本就是通過反射把所謂的工廠實例來生成,過程中需要的參數(shù)實例都通過配置的工廠類型來創(chuàng)建枫夺,這些用到的所有類型都通過方法定義來配置将宪,所有的方法都會封裝成包含方法反射信息的對象,之后需要的時候通過反射來調(diào)用對應方法來生成需要的實例筷屡。

    下面通過代碼來看看是如何實現(xiàn)的涧偷。

  • 代碼入口

    上次追溯到在BuildActionsFactory的runBuildInProcess方法中:

    private Runnable runBuildInProcess(StartParameterInternal startParameter, DaemonParameters daemonParameters) {
        ServiceRegistry globalServices = ServiceRegistryBuilder.builder().displayName("Global services").parent(this.loggingServices).parent(NativeServices.getInstance()).provider(new GlobalScopeServices(startParameter.isContinuous())).build();
        return this.runBuildAndCloseServices(startParameter, daemonParameters, (BuildActionExecuter)globalServices.get(BuildExecuter.class), globalServices, globalServices.get(GradleUserHomeScopeServiceRegistry.class));
    }
    

    這個方法里有一句(BuildActionExecuter)globalServices.get(BuildExecuter.class),這句代碼返回的對象就是傳遞下去的this.executer毙死,很顯然它是一個BuildActionExecuter類型,但是它的實現(xiàn)類我們現(xiàn)在無法得知喻鳄,需要通過globalServices.get(BuildExecuter.class)來查找扼倘。

    globalServices通過ServiceRegistryBuilder.builder()的build方法生成:

    public ServiceRegistry build() {
          //這里的parents傳遞數(shù)組只會包含第一個元素
        DefaultServiceRegistry registry = new DefaultServiceRegistry(this.displayName, (ServiceRegistry[])this.parents.toArray(new ServiceRegistry[0]));
        Iterator var2 = this.providers.iterator();
          
        while(var2.hasNext()) {
            Object provider = var2.next();
            registry.addProvider(provider);
        }
    
        return registry;
    }
    

    可見返回了一個DefaultServiceRegistry對象,而這個對象就是整個工廠模式的入口除呵。

  • DefaultServiceRegistry

    從名字上可以看出再菊,這是一個默認的服務注冊的地方。來看一下它的構(gòu)造方法:

    private final OwnServices ownServices;
    private final ServiceProvider allServices;
    private final ServiceProvider parentServices;
    private final String displayName;
    private final ServiceProvider thisAsServiceProvider;
    
    public DefaultServiceRegistry(String displayName, ServiceRegistry... parents) {
        this.state = new AtomicReference(DefaultServiceRegistry.State.INIT);
        this.displayName = displayName;
        this.ownServices = new OwnServices();
        if (parents.length == 0) {
            this.parentServices = null;
            this.allServices = this.ownServices;
        } else {
            this.parentServices = setupParentServices(parents);
            this.allServices = new CompositeServiceProvider(new ServiceProvider[]{this.ownServices, this.parentServices});
        }
    
        this.thisAsServiceProvider = this.allServices;
        this.findProviderMethods(this);
    }
    

    回看前面的ServiceRegistryBuilder.builder的build方法颜曾,發(fā)現(xiàn)parent方法其實是把參數(shù)傳遞給DefaultServiceRegistry的parentServices纠拔,而provider方法則是通過addProvider方法把參數(shù)傳遞給了ownServices:

    public DefaultServiceRegistry addProvider(Object provider) {
        this.assertMutable();
        this.findProviderMethods(provider);
        return this;
    }
    

    findProviderMethods方法只在兩個地方調(diào)用,一個是構(gòu)造方法里泛豪,傳入的當前的DefaultServiceRegistry對象稠诲,還有就是通過addProvider方法調(diào)用的。

  • globalServices.get(BuildExecuter.class)

    public <T> T get(Class<T> serviceType) throws UnknownServiceException, ServiceLookupException {
        return serviceType.cast(this.get((Type)serviceType));
    }
    
    public Object get(Type serviceType) throws UnknownServiceException, ServiceLookupException {
        Object instance = this.find(serviceType);
        if (instance == null) {
            throw new UnknownServiceException(serviceType, String.format("No service of type %s available in %s.", format(serviceType), this.getDisplayName()));
        } else {
            return instance;
        }
    }
    
    public Object find(Type serviceType) throws ServiceLookupException {
        assertValidServiceType(unwrap(serviceType));
        Service provider = this.getService(serviceType);
        return provider == null ? null : provider.get();
    }
    
    private Service getService(Type serviceType) {
        this.serviceRequested();
        return find(serviceType, this.allServices);
    }
    
    private static Service find(Type serviceType, ServiceProvider serviceProvider) {
        if (serviceType instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType)serviceType;
            Type rawType = parameterizedType.getRawType();
            Type typeArg;
            if (rawType.equals(Factory.class)) {
                typeArg = parameterizedType.getActualTypeArguments()[0];
                return getFactoryService(typeArg, serviceProvider);
            }
    
            if (rawType instanceof Class) {
                if (((Class)rawType).isAssignableFrom(List.class)) {
                    typeArg = parameterizedType.getActualTypeArguments()[0];
                    return getCollectionService(typeArg, serviceProvider);
                }
    
                assertValidServiceType((Class)rawType);
                return serviceProvider.getService(serviceType);
            }
        }
    
        if (serviceType instanceof Class) {
            assertValidServiceType((Class)serviceType);
            return serviceProvider.getService(serviceType);
        } else {
            throw new ServiceValidationException(String.format("Locating services with type %s is not supported.", format(serviceType)));
        }
    }
    

    可以看到诡曙,這里的get方法最終就是調(diào)用了DefaultServiceRegistry的allServices的getService方法臀叙。

    通過前面的構(gòu)造方法可以知道,parents不為空的情況下价卤,allServices就是CompositeServiceProvider劝萤,而他的getService就是遍歷它的ServiceProvider[](也就是ownServices和parentServices),調(diào)用它們的getService方法找到第一個不為空的Service返回慎璧。

  • findProviderMethods

    private void findProviderMethods(Object target) {
        Class<?> type = target.getClass();
        RelevantMethods methods = RelevantMethods.getMethods(type);
        Iterator var4 = methods.decorators.iterator();
    
        ServiceMethod method;
        while(var4.hasNext()) {
            method = (ServiceMethod)var4.next();
            if (this.parentServices == null) {
                throw new ServiceLookupException(String.format("Cannot use decorator method %s.%s() when no parent registry is provided.", type.getSimpleName(), method.getName()));
            }
    
            this.ownServices.add(new FactoryMethodService(this, target, method));
        }
    
        var4 = methods.factories.iterator();
    
        while(var4.hasNext()) {
            method = (ServiceMethod)var4.next();
            this.ownServices.add(new FactoryMethodService(this, target, method));
        }
    
        var4 = methods.configurers.iterator();
    
        while(var4.hasNext()) {
            method = (ServiceMethod)var4.next();
            this.applyConfigureMethod(method, target);
        }
    
    }
    

    這個方法一開始就會根據(jù)target的類型檢索出所有的方法信息并封裝成方法信息對象床嫌,放在不同的數(shù)組里跨释,總共有三種。

  • RelevantMethods.getMethods(type)

    public static RelevantMethods getMethods(Class<?> type) {
        RelevantMethods relevantMethods = (RelevantMethods)METHODS_CACHE.get(type);
        if (relevantMethods == null) {
            relevantMethods = buildRelevantMethods(type);
            METHODS_CACHE.putIfAbsent(type, relevantMethods);
        }
    
        return relevantMethods;
    }
    

    實際上通過buildRelevantMethods方法生成RelevantMethods:

    private static RelevantMethods buildRelevantMethods(Class<?> type) {
        RelevantMethodsBuilder builder = new RelevantMethodsBuilder(type);
        addDecoratorMethods(builder);
        addFactoryMethods(builder);
        addConfigureMethods(builder);
        RelevantMethods relevantMethods = builder.build();
        return relevantMethods;
    }
    

    這里的三個方法分別會生成RelevantMethods的decorators,厌处、factories鳖谈、configurers。

    • addDecoratorMethods

      private static void addDecoratorMethods(RelevantMethodsBuilder builder) {
          Class<?> type = builder.type;
          Iterator<Method> iterator = builder.remainingMethods.iterator();
      
          while(true) {
              Method method;
              do {
                  if (!iterator.hasNext()) {
                      return;
                  }
      
                  method = (Method)iterator.next();
              } while(!method.getName().startsWith("create") && !method.getName().startsWith("decorate"));
      
              if (method.getReturnType().equals(Void.TYPE)) {
                  throw new ServiceLookupException(String.format("Method %s.%s() must not return void.", type.getSimpleName(), method.getName()));
              }
                      //這個方法會判斷方法的參數(shù)類型中是否有和其返回類型一樣的
              if (takesReturnTypeAsParameter(method)) {
                  builder.add(iterator, builder.decorators, method);
              }
          }
      }
      

      可以看到這里會把所有以create或decorate開頭的嘱蛋、且參數(shù)類型中有和其返回類型一樣的方法都添加到decorators中蚯姆。

    • addFactoryMethods

      private static void addFactoryMethods(RelevantMethodsBuilder builder) {
          Class<?> type = builder.type;
          Iterator<Method> iterator = builder.remainingMethods.iterator();
      
          while(iterator.hasNext()) {
              Method method = (Method)iterator.next();
              if (method.getName().startsWith("create") && !Modifier.isStatic(method.getModifiers())) {
                  if (method.getReturnType().equals(Void.TYPE)) {
                      throw new ServiceLookupException(String.format("Method %s.%s() must not return void.", type.getSimpleName(), method.getName()));
                  }
      
                  builder.add(iterator, builder.factories, method);
              }
          }
      
      }
      

      這里會把create開頭的、非靜態(tài)的方法都添加到factories中洒敏。

    • addConfigureMethods

      private static void addConfigureMethods(RelevantMethodsBuilder builder) {
          Class<?> type = builder.type;
          Iterator<Method> iterator = builder.remainingMethods.iterator();
      
          while(iterator.hasNext()) {
              Method method = (Method)iterator.next();
              if (method.getName().equals("configure")) {
                  if (!method.getReturnType().equals(Void.TYPE)) {
                      throw new ServiceLookupException(String.format("Method %s.%s() must return void.", type.getSimpleName(), method.getName()));
                  }
      
                  builder.add(iterator, builder.configurers, method);
              }
          }
      
      }
      

      這里會把名叫configure的方法都添加到configurers中龄恋。

    這三種方法的返回類型都不能是void,因為我們工廠方法是用來生產(chǎn)特定類型實例的凶伙,所以也很好理解郭毕。

    上面的remainingMethods來自于RelevantMethodsBuilder的構(gòu)造方法:

    RelevantMethodsBuilder(Class<?> type) {
        this.type = type;
        this.remainingMethods = new LinkedList();
    
        for(Class<?> clazz = type; clazz != Object.class && clazz != DefaultServiceRegistry.class; clazz = clazz.getSuperclass()) {
            this.remainingMethods.addAll(Arrays.asList(clazz.getDeclaredMethods()));
        }
    
    }
    

    可以看到,remainingMethods包含了目標類和其所有父類(不包含Object和DefaultServiceRegistry)的所有方法函荣。

    接下來显押,我們來看findProviderMethods下面的操作。

  • findProviderMethods接下來的操作

    反射得到方法信息數(shù)組之后呢傻挂,接下來會遍歷decorators和factories數(shù)組的元素乘碑,對其每一個都封裝進一個FactoryMethodService實例,并添加到ownServices中金拒,OwnServices的add方法如下:

    public void add(ServiceProvider serviceProvider) {
        DefaultServiceRegistry.this.assertMutable();
        if (!(serviceProvider instanceof SingletonService)) {
            throw new UnsupportedOperationException("Unsupported service provider type: " + serviceProvider);
        } else {
            this.stoppable.add(serviceProvider);
              //這里的兩個參數(shù)其實就是key和value值
            this.analyser.addProviderForClassHierarchy(((SingletonService)serviceProvider).serviceClass, serviceProvider);
        }
    }
    

    analyser是ProviderAnalyser類型兽肤,OwnServices的一個內(nèi)部類,addProviderForClassHierarchy方法最終會以方法的返回類型(包括這個類的所有父類绪抛,因為子類一定可以類型轉(zhuǎn)換成其父類的)為key资铡,F(xiàn)actoryMethodService為value添加到OwnServices的providersByType這個Map中,后面我們會看到哪里會用到它幢码。

    最后一種configurers數(shù)組元素會通過applyConfigureMethod方法遍歷執(zhí)行每一個的configure方法:

    private void applyConfigureMethod(ServiceMethod method, Object target) {
        Object[] params = new Object[method.getParameterTypes().length];
    
        for(int i = 0; i < method.getParameterTypes().length; ++i) {
            Type paramType = method.getParameterTypes()[i];
            if (paramType.equals(ServiceRegistration.class)) {
                params[i] = this.newRegistration();
            } else {
                Service paramProvider = find(paramType, this.allServices);
                if (paramProvider == null) {
                    throw new ServiceLookupException(String.format("Cannot configure services using %s.%s() as required service of type %s is not available.", method.getOwner().getSimpleName(), method.getName(), format(paramType)));
                }
    
                params[i] = paramProvider.get();
            }
        }
    
        try {
            method.invoke(target, params);
        } catch (Exception var7) {
            throw new ServiceLookupException(String.format("Could not configure services using %s.%s().", method.getOwner().getSimpleName(), method.getName()), var7);
        }
    }
    

    注意笤休,這里的方法參數(shù)構(gòu)造除了ServiceRegistration類型之外,其他的類型都是通過find方法去創(chuàng)建症副,這和一開始的get(BuildExecuter.class)最終調(diào)用的find方法一樣店雅。 這就是巧妙的地方,我們通過同一套邏輯不僅可以構(gòu)造目標Service瓦糕,而且在過程中需要的中間Service實例也可以構(gòu)造底洗,我們要做的就是在DefaultServiceRegistry的實現(xiàn)類中定義好可以產(chǎn)生對應類型的方法及其構(gòu)造邏輯即可。

    但是經(jīng)過查找咕娄,this.loggingServices(也就是CommandLineLogging)和NativeServices中都沒有定義返回類型是BuildExecuter的方法亥揖,它們也沒有配置parentServices、沒有給ownServices添加額外的ServiceProvider,好像查找過程被打斷了...不要慌费变,我們還有一個configure方法沒有看摧扇,或許有其他的Service在那里被注冊了,這個方法在findProviderMethods流程中被調(diào)用過挚歧。

    我們在GlobalScopeServices中找到了這個方法(還記得嗎扛稽,這個類在開頭通過provider方法傳入到findProviderMethods流程):

    void configure(ServiceRegistration registration, ClassLoaderRegistry classLoaderRegistry) {
        registration.add(ClassLoaderScopeListeners.class);
        List<PluginServiceRegistry> pluginServiceFactories = (new DefaultServiceLocator(new ClassLoader[]{classLoaderRegistry.getRuntimeClassLoader(), classLoaderRegistry.getPluginsClassLoader()})).getAll(PluginServiceRegistry.class);
        Iterator var4 = pluginServiceFactories.iterator();
    
        while(var4.hasNext()) {
            PluginServiceRegistry pluginServiceRegistry = (PluginServiceRegistry)var4.next();
              //添加到DefaultServiceRegistry的ownServices中
            registration.add(PluginServiceRegistry.class, pluginServiceRegistry);
              //雙向綁定
            pluginServiceRegistry.registerGlobalServices(registration);
        }
    }
    

    那么通過上面的applyConfigureMethod方法得知,configure方法的第一個參數(shù)通過newRegistration方法構(gòu)造:

    private ServiceRegistration newRegistration() {
        return new ServiceRegistration() {
            public <T> void add(Class<T> serviceType, T serviceInstance) {
                DefaultServiceRegistry.this.add(serviceType, serviceInstance);
            }
    
            public void add(Class<?> serviceType) {
                DefaultServiceRegistry.this.ownServices.add(new ConstructorService(DefaultServiceRegistry.this, serviceType));
            }
    
            public void addProvider(Object provider) {
                DefaultServiceRegistry.this.addProvider(provider);
            }
        };
    }
    
    public <T> DefaultServiceRegistry add(Class<T> serviceType, T serviceInstance) {
        this.assertMutable();
        this.ownServices.add(new FixedInstanceService(this, serviceType, serviceInstance));
        return this;
    }
    

    第二個參數(shù)則又是通過這種工廠方法去調(diào)用find查找滑负,我們在GlobalScopeServices中找到了這個注冊方法:

    ClassLoaderRegistry createClassLoaderRegistry(ClassPathRegistry classPathRegistry, LegacyTypesSupport legacyTypesSupport) {
        return (ClassLoaderRegistry)(GradleRuntimeShadedJarDetector.isLoadedFrom(this.getClass()) ? new FlatClassLoaderRegistry(this.getClass().getClassLoader()) : new DefaultClassLoaderRegistry(classPathRegistry, legacyTypesSupport, DirectInstantiator.INSTANCE));
    }
    

    這里只是知道configure的參數(shù)是怎么通過工廠模式方法構(gòu)造的即可在张,具體用的哪個ClassLoaderRegistry不影響流程。

    我們看一下DefaultServiceLocator的getAll方法:

    public <T> List<T> getAll(Class<T> serviceType) throws UnknownServiceException {
        List<ServiceFactory<T>> factories = this.findFactoriesForServiceType(serviceType);
        ArrayList<T> services = new ArrayList();
        Iterator var4 = factories.iterator();
    
        while(var4.hasNext()) {
            ServiceFactory<T> factory = (ServiceFactory)var4.next();
            services.add(factory.create());
        }
    
        return services;
    }
    
    private <T> List<ServiceFactory<T>> findFactoriesForServiceType(Class<T> serviceType) {
        return this.factoriesFor(serviceType, this.implementationsOf(serviceType));
    }
    
    private <T> List<ServiceFactory<T>> factoriesFor(Class<T> serviceType, List<Class<? extends T>> implementationClasses) {
        List<ServiceFactory<T>> factories = new ArrayList();
        Iterator var4 = implementationClasses.iterator();
    
        while(var4.hasNext()) {
            Class<? extends T> implementationClass = (Class)var4.next();
            factories.add(new ServiceFactory(serviceType, implementationClass));
        }
    
        return factories;
    }
    

    上面代碼的流程是矮慕,返回一個ArrayList<PluginServiceRegistry> 帮匾,每一個PluginServiceRegistry都來自于ServiceFactory的create方法:

    public T create() {
        return this.newInstance();
    }
    
    public T newInstance(Object... params) {
        try {
            return DirectInstantiator.instantiate(this.implementationClass, params);
        } catch (ObjectInstantiationException var3) {
            ObjectInstantiationException t = var3;
            throw new RuntimeException(String.format("Could not create an implementation of service '%s'.", this.serviceType.getName()), t);
        }
    }
    

    其實就是通過反射來構(gòu)造一個無參構(gòu)造方法生成實例。那Class來自哪里呢痴鳄,繼續(xù)看implementationsOf方法瘟斜,這個方法實際上調(diào)用了findServiceImplementations方法:

    private <T> List<Class<? extends T>> findServiceImplementations(Class<T> serviceType) throws IOException {
        String resourceName = "META-INF/services/" + serviceType.getName();
        Set<String> implementationClassNames = new HashSet();
        List<Class<? extends T>> implementations = new ArrayList();
        Iterator var5 = this.classLoaders.iterator();
    
        while(var5.hasNext()) {
            ClassLoader classLoader = (ClassLoader)var5.next();
            Enumeration<URL> resources = classLoader.getResources(resourceName);
    
            while(resources.hasMoreElements()) {
                URL resource = (URL)resources.nextElement();
    
                List implementationClassNamesFromResource;
                try {
                    implementationClassNamesFromResource = this.extractImplementationClassNames(resource);
                      ...
                }...
    
                Iterator var15 = implementationClassNamesFromResource.iterator();
    
                while(var15.hasNext()) {
                    String implementationClassName = (String)var15.next();
                    if (implementationClassNames.add(implementationClassName)) {
                        try {
                            Class<?> implClass = classLoader.loadClass(implementationClassName);
                              ...
                            implementations.add(implClass.asSubclass(serviceType));
                        } ...
                    }
                }
            }
        }
    
        return implementations;
    }
    

    在源碼的META-INF/services/路徑下找到org.gradle.internal.service.scopes.PluginServiceRegistry文件:

    org.gradle.tooling.internal.provider.LauncherServices
    org.gradle.caching.internal.BuildCacheServices
    org.gradle.internal.service.scopes.ExecutionServices
    org.gradle.internal.service.scopes.VirtualFileSystemServices
    org.gradle.internal.build.event.BuildEventServices
    org.gradle.workers.internal.WorkersServices
    org.gradle.api.internal.artifacts.DependencyServices
    org.gradle.composite.internal.CompositeBuildServices
    org.gradle.plugin.internal.PluginUsePluginServiceRegistry
    org.gradle.internal.resource.transport.http.HttpResourcesPluginServiceRegistry
    org.gradle.vcs.internal.services.VersionControlServices
    org.gradle.caching.http.internal.HttpBuildCacheServiceServices
    org.gradle.buildinit.plugins.internal.services.BuildInitServices
    org.gradle.api.reporting.components.internal.DiagnosticsServices
    org.gradle.plugins.ide.internal.tooling.ToolingModelServices
    org.gradle.plugins.ide.internal.IdeServices
    org.gradle.ide.xcode.internal.services.XcodeServices
    org.gradle.api.publish.ivy.internal.IvyServices
    org.gradle.api.internal.tasks.compile.GroovyServices
    org.gradle.language.java.internal.JavaToolChainServiceRegistry
    org.gradle.language.java.internal.JavaLanguagePluginServiceRegistry
    org.gradle.language.jvm.internal.JvmPluginServiceRegistry
    org.gradle.language.nativeplatform.internal.registry.NativeLanguageServices
    org.gradle.language.scala.internal.toolchain.ScalaToolChainServiceRegistry
    org.gradle.api.publish.maven.internal.MavenPublishServices
    org.gradle.platform.base.internal.registry.ComponentModelBaseServiceRegistry
    org.gradle.jvm.internal.services.PlatformJvmServices
    org.gradle.nativeplatform.internal.services.NativeBinaryServices
    org.gradle.play.internal.toolchain.PlayToolChainServiceRegistry
    org.gradle.api.internal.tasks.CompileServices
    org.gradle.api.plugins.internal.PluginAuthorServices
    org.gradle.api.publish.internal.service.PublishServices
    org.gradle.internal.resource.transport.gcp.gcs.GcsResourcesPluginServiceRegistry
    org.gradle.internal.resource.transport.aws.s3.S3ResourcesPluginServiceRegistry
    org.gradle.internal.resource.transport.sftp.SftpResourcesPluginServiceRegistry
    org.gradle.api.internal.tasks.testing.TestingBasePluginServiceRegistry
    org.gradle.jvm.test.internal.services.JvmTestingServices
    org.gradle.nativeplatform.test.internal.services.NativeTestingServices
    org.gradle.language.cpp.internal.tooling.ToolingNativeServices
    

    所有注冊的PluginServiceRegistry都在這了。

    逐一查找他們的registerGlobalServices方法痪寻,最終在第一個類——LauncherServices中找到:

    public void registerGlobalServices(ServiceRegistration registration) {
        registration.addProvider(new ToolingGlobalScopeServices());
    }
    

    ToolingGlobalScopeServices中找到了返回BuildExecuter類型的注冊方法:

    BuildExecuter createBuildExecuter(List<BuildActionRunner> buildActionRunners, List<BuildEventListenerFactory> registrations, ListenerManager listenerManager, BuildOperationListenerManager buildOperationListenerManager, TaskInputsListeners inputsListeners, StyledTextOutputFactory styledTextOutputFactory, ExecutorFactory executorFactory, LoggingManagerInternal loggingManager, GradleUserHomeScopeServiceRegistry userHomeServiceRegistry, FileSystemChangeWaiterFactory fileSystemChangeWaiterFactory) {
        return new SetupLoggingActionExecuter(new SessionFailureReportingActionExecuter(new StartParamsValidatingActionExecuter(new GradleThreadBuildActionExecuter(new SessionScopeBuildActionExecuter(new SubscribableBuildActionExecuter(new ContinuousBuildActionExecuter(new BuildTreeScopeBuildActionExecuter(new InProcessBuildActionExecuter(new RunAsBuildOperationBuildActionRunner(new BuildCompletionNotifyingBuildActionRunner(new ValidatingBuildActionRunner(new BuildOutcomeReportingBuildActionRunner(new ChainingBuildActionRunner(buildActionRunners), styledTextOutputFactory)))))), fileSystemChangeWaiterFactory, inputsListeners, styledTextOutputFactory, executorFactory), listenerManager, buildOperationListenerManager, registrations), userHomeServiceRegistry))), styledTextOutputFactory, Time.clock()), loggingManager);
    }
    

    很明顯螺句,這又是一個代理模式蛇尚,一級一級地往下傳遞執(zhí)行execute方法佣蓉,就不一一貼源碼了,這里只大概描述每個Executer的作用:

    • SetupLoggingActionExecuter

      啟動日志輸出程序义辕,監(jiān)聽執(zhí)行過程并輸出build過程日志寓盗,在代理鏈執(zhí)行完成后stop傀蚌。

    • SessionFailureReportingActionExecuter

      給build過程包裹try塊善炫,在發(fā)生異常時解析異常信息并輸出日志。

    • StartParamsValidatingActionExecuter

      獲取StartParameter宪萄,如果配置了的話則檢查它的buildFile拜英、settings.gradle琅催、initScripts文件是否存在。

    • GradleThreadBuildActionExecuter

      這里會配一個靜態(tài)的ThreadLocal對象來標志當前是否正在build侠碧,設(shè)置為true舆床,在build結(jié)束后置為false嫁佳,避免重復構(gòu)建沖突蒿往。

    • SessionScopeBuildActionExecuter

      build session生命周期的監(jiān)聽瓤漏。

    • SubscribableBuildActionExecuter

      一些外部添加的監(jiān)聽蔬充。

    • ContinuousBuildActionExecuter

      這里會根據(jù)是否開啟了持續(xù)性構(gòu)建配置而分成兩個分支饥漫,持續(xù)性構(gòu)建邏輯和非持續(xù)性構(gòu)建庸队。

    • BuildTreeScopeBuildActionExecuter

      構(gòu)建一個BuildTreeScopeServices對象傳遞到execute中彻消。

    • InProcessBuildActionExecuter

      public BuildActionResult execute(final BuildAction action, final BuildRequestContext buildRequestContext, BuildActionParameters actionParameters, ServiceRegistry contextServices) {
          //得到的是DefaultIncludedBuildRegistry
          BuildStateRegistry buildRegistry = (BuildStateRegistry)contextServices.get(BuildStateRegistry.class);
          final PayloadSerializer payloadSerializer = (PayloadSerializer)contextServices.get(PayloadSerializer.class);
          BuildOperationNotificationValve buildOperationNotificationValve = (BuildOperationNotificationValve)contextServices.get(BuildOperationNotificationValve.class);
          buildOperationNotificationValve.start();
      
          BuildActionResult var9;
          try {
              //得到DefaultRootBuildState
              RootBuildState rootBuild = buildRegistry.createRootBuild(BuildDefinition.fromStartParameter(action.getStartParameter(), (PublicBuildPath)null));
              var9 = (BuildActionResult)rootBuild.run(new Transformer<BuildActionResult, BuildController>() {
                  public BuildActionResult transform(BuildController buildController) {
                      //buildController是GradleBuildController
                      BuildActionRunner.Result result = InProcessBuildActionExecuter.this.buildActionRunner.run(action, buildController);
                      if (result.getBuildFailure() == null) {
                          return BuildActionResult.of(payloadSerializer.serialize(result.getClientResult()));
                      } else {
                          return buildRequestContext.getCancellationToken().isCancellationRequested() ? BuildActionResult.cancelled(payloadSerializer.serialize(result.getBuildFailure())) : BuildActionResult.failed(payloadSerializer.serialize(result.getClientFailure()));
                      }
                  }
              });
          } finally {
              buildOperationNotificationValve.stop();
          }
      
          return var9;
      }
      

      這里通過DefaultRootBuildState的run方法得到一個GradleBuildController對象:

      public <T> T run(Transformer<T, ? super BuildController> buildAction) {
          //this.gradleLauncher是DefaultGradleLauncher
          GradleBuildController buildController = new GradleBuildController(this.gradleLauncher);
          RootBuildLifecycleListener buildLifecycleListener = (RootBuildLifecycleListener)this.listenerManager.getBroadcaster(RootBuildLifecycleListener.class);
          GradleInternal gradle = buildController.getGradle();
          buildLifecycleListener.afterStart(gradle);
      
          Object var5;
          try {
              var5 = buildAction.transform(buildController);
          } finally {
              buildLifecycleListener.beforeComplete(gradle);
          }
      
          return var5;
      }
      

      繼續(xù)往下走宾尚,InProcessBuildActionExecuter.this.buildActionRunner就是下一級的RunAsBuildOperationBuildActionRunner丙笋。

    • RunAsBuildOperationBuildActionRunner

      一些監(jiān)聽、日志不见。接著繼續(xù)往下執(zhí)行BuildCompletionNotifyingBuildActionRunner的run方法澳化。

    • BuildCompletionNotifyingBuildActionRunner

      通知監(jiān)聽器build的結(jié)果成功或失敗稳吮。

    • ValidatingBuildActionRunner

      public BuildActionRunner.Result run(BuildAction action, BuildController buildController) {
          BuildActionRunner.Result result = this.delegate.run(action, buildController);
          if (!result.hasResult()) {
              throw new UnsupportedOperationException(String.format("Don't know how to run a build action of type %s.", action.getClass().getSimpleName()));
          } else {
              return result;
          }
      }
      

      這里只是簡單的判斷結(jié)果是否為空并作出提示缎谷。

    • BuildOutcomeReportingBuildActionRunner

      輸出結(jié)果信息,比如構(gòu)建時間等列林。

    • ChainingBuildActionRunner

      前面所有的都是對整個流程的監(jiān)聽、添加相應日志等操作酪惭,最后這一步才會觸發(fā)最終的執(zhí)行希痴。這里會遍歷ToolingGlobalScopeServices的createBuildExecuter方法的傳參buildActionRunners中的所有的BuildActionRunner,也是通過相同的工廠模式獲取的砌创,經(jīng)過查找,找到了這里的BuildActionRunner實現(xiàn)類是ExecuteBuildActionRunner嫩实,它的run方法如下:

      public BuildActionRunner.Result run(BuildAction action, BuildController buildController) {
          if (!(action instanceof ExecuteBuildAction)) {
              return Result.nothing();
          } else {
              try {
                  buildController.run();
                  return Result.of((Object)null);
              } catch (RuntimeException var4) {
                  RuntimeException e = var4;
                  return Result.failed(e);
              }
          }
      }
      

      可見這里是調(diào)用了前面GradleBuildController的run方法:

      public GradleInternal run() {
          //注意這里使用了java8的新特性 ‘::’
          return this.doBuild(BuildType.TASKS, GradleLauncher::executeTasks);
      }
      
      private GradleInternal doBuild(final GradleInternal.BuildType buildType, final Action<? super GradleLauncher> build) {
          GradleInternal var3;
          try {
              var3 = (GradleInternal)this.workerLeaseService.withLocks(Collections.singleton(this.workerLeaseService.getWorkerLease()), new Factory<GradleInternal>() {
                  public GradleInternal create() {
                      GradleInternal gradle = GradleBuildController.this.getGradle();
      
                      try {
                          gradle.setBuildType(buildType);
                          GradleLauncher launcher = GradleBuildController.this.getLauncher();
                          //實際上是執(zhí)行l(wèi)auncher的executeTasks方法
                          build.execute(launcher);
                          launcher.finishBuild();
                      } finally {
                          gradle.setBuildType(BuildType.NONE);
                      }
      
                      return gradle;
                  }
              });
          } finally {
              this.state = GradleBuildController.State.Completed;
          }
      
          return var3;
      }
      
      //Action.java
      public interface Action<T> {
          void execute(T var1);
      }
      

      launcher是DefaultGradleLauncher晃洒,它的executeTasks方法如下:

      public GradleInternal executeTasks() {
          this.doBuildStages(DefaultGradleLauncher.Stage.RunTasks);
          return this.gradle;
      }
      
      private void doBuildStages(Stage upTo) {
          Preconditions.checkArgument(upTo != DefaultGradleLauncher.Stage.Finished, "Stage.Finished is not supported by doBuildStages.");
      
          try {
              //這里還會判斷是否可以立即執(zhí)行
              if (upTo == DefaultGradleLauncher.Stage.RunTasks && this.instantExecution.canExecuteInstantaneously()) {
                  this.doInstantExecution();
              } else {
                  this.doClassicBuildStages(upTo);
              }
          } catch (Throwable var3) {
              Throwable t = var3;
              this.finishBuild(upTo.getDisplayName(), t);
          }
      }
      
      private void doInstantExecution() {
          this.buildListener.buildStarted(this.gradle);
          this.instantExecution.loadScheduledWork();
          this.stage = DefaultGradleLauncher.Stage.TaskGraph;
          this.runWork();
      }
      

      如果不符合立即執(zhí)行條件則調(diào)用doClassicBuildStages方法:

      private void doClassicBuildStages(Stage upTo) {
          if (this.stage == null) {
              this.instantExecution.prepareForBuildLogicExecution();
          }
      
          this.prepareSettings();
          if (upTo != DefaultGradleLauncher.Stage.LoadSettings) {
              this.prepareProjects();
              if (upTo != DefaultGradleLauncher.Stage.Configure) {
                  this.prepareTaskExecution();
                  if (upTo != DefaultGradleLauncher.Stage.TaskGraph) {
                      this.instantExecution.saveScheduledWork();
                      this.runWork();
                  }
              }
          }
      }
      

      可見,兩個分支最終都會執(zhí)行runWork方法呻疹,根據(jù)名字猜測前面的prepareSettings桶略、prepareProjects和prepareTaskExecution似乎和根據(jù)gradle配置文件轉(zhuǎn)化成對應的代碼有關(guān),這些方法內(nèi)部都使用了DefaultGradleLauncher的內(nèi)部字段诲宇,他們通過其構(gòu)造方法傳入,看來我們得去找找這個構(gòu)造入口惶翻。

      見下一篇姑蓝。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市吕粗,隨后出現(xiàn)的幾起案子纺荧,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宙暇,死亡現(xiàn)場離奇詭異输枯,居然都是意外死亡,警方通過查閱死者的電腦和手機占贫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門桃熄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人型奥,你說我怎么就攤上這事瞳收。” “怎么了厢汹?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵螟深,是天一觀的道長。 經(jīng)常有香客問我烫葬,道長界弧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任搭综,我火速辦了婚禮垢箕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘设凹。我一直安慰自己舰讹,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布闪朱。 她就那樣靜靜地躺著月匣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奋姿。 梳的紋絲不亂的頭發(fā)上锄开,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音称诗,去河邊找鬼萍悴。 笑死,一個胖子當著我的面吹牛寓免,可吹牛的內(nèi)容都是我干的癣诱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼袜香,長吁一口氣:“原來是場噩夢啊……” “哼撕予!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蜈首,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤实抡,失蹤者是張志新(化名)和其女友劉穎欠母,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吆寨,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡赏淌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了啄清。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片六水。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖盒延,靈堂內(nèi)的尸體忽然破棺而出缩擂,到底是詐尸還是另有隱情,我是刑警寧澤添寺,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布胯盯,位于F島的核電站,受9級特大地震影響计露,放射性物質(zhì)發(fā)生泄漏博脑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一票罐、第九天 我趴在偏房一處隱蔽的房頂上張望叉趣。 院中可真熱鬧,春花似錦该押、人聲如沸疗杉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烟具。三九已至,卻和暖如春奠蹬,著一層夾襖步出監(jiān)牢的瞬間朝聋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工囤躁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留冀痕,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓狸演,卻偏偏與公主長得像言蛇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子宵距,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容