> ***两个核心功能:***
> - 下载依赖
> - 执行插件目标
```java
private void execute(MavenSession session, MojoExecution mojoExecution, ProjectIndex projectIndex,
DependencyContext dependencyContext) throws LifecycleExecutionException {
List<MavenProject> forkedProjects = executeForkedExecutions(mojoExecution, session, projectIndex);
// 核心一: 下载依赖
ensureDependenciesAreResolved(mojoDescriptor, session, dependencyContext); // todo : 核心,解析依赖
eventCatapult.fire(ExecutionEvent.Type.MojoStarted, session, mojoExecution);
try {
try { // 核心二执行目标
pluginManager.executeMojo(session, mojoExecution); // 执行插件目标
} catch (MojoFailure | PluginManager | PluginConfiguration | MojoExecution e) {
throw new LifecycleExecutionException(mojoExecution, session.getCurrentProject(), e);
}
eventCatapult.fire(ExecutionEvent.Type.MojoSucceeded, session, mojoExecution); // 发布事件
} catch (LifecycleExecutionException e) {
eventCatapult.fire(ExecutionEvent.Type.MojoFailed, session, mojoExecution, e);
throw e;
} finally {
for (MavenProject forkedProject : forkedProjects) {
forkedProject.setExecutionProject(null);
}
}
}
```
两个核心单独看
依赖下载
- org.apache.maven.lifecycle.internal.MojoExecutor#ensureDependenciesAreResolved
public void ensureDependenciesAreResolved(MojoDescriptor mojoDescriptor, MavenSession session,
DependencyContext dependencyContext) throws LifecycleExecutionException {
MavenProject project = dependencyContext.getProject();
boolean aggregating = mojoDescriptor.isAggregator(); // 看看是否是聚合工程
if (dependencyContext.isResolutionRequiredForCurrentProject()) {
Collection<String> scopesToCollect = dependencyContext.getScopesToCollectForCurrentProject();
Collection<String> scopesToResolve = dependencyContext.getScopesToResolveForCurrentProject();
lifeCycleDependencyResolver.resolveProjectDependencies(project, scopesToCollect, scopesToResolve, session,
aggregating, Collections.<Artifact>emptySet()); // todo 核心
dependencyContext.synchronizeWithProjectState();
}
if (aggregating) { // 聚合工程
Collection<String> scopesToCollect = toScopes(mojoDescriptor.getDependencyCollectionRequired());
Collection<String> scopesToResolve = toScopes(mojoDescriptor.getDependencyResolutionRequired());
if (dependencyContext.isResolutionRequiredForAggregatedProjects(scopesToCollect, scopesToResolve)) {
for (MavenProject aggregatedProject : session.getProjects()) { // 为什么没有递归? 是因为解析pom反应堆时候已经拉平了树结构了吗?
if (aggregatedProject != project) {
lifeCycleDependencyResolver.resolveProjectDependencies(aggregatedProject, scopesToCollect,
scopesToResolve, session, aggregating, Collections.<Artifact>emptySet()); // todo 核心
}
}
}
}
ArtifactFilter artifactFilter = getArtifactFilter(mojoDescriptor);
List<MavenProject> projectsToResolve = LifecycleDependencyResolver.getProjects(session.getCurrentProject(),
session, mojoDescriptor.isAggregator());
for (MavenProject projectToResolve : projectsToResolve) {
projectToResolve.setArtifactFilter(artifactFilter);
}
}
-
org.apache.maven.lifecycle.internal.LifecycleDependencyResolver#getDependencies
-
org.apache.maven.project.DefaultProjectDependenciesResolver#resolve
-
org.eclipse.aether.internal.impl.DefaultRepositorySystem#collectDependencies
-
org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector#collectDependencies
-
org.apache.maven.repository.internal.DefaultArtifactDescriptorReader#readArtifactDescriptor
-
…
-
org.eclipse.aether.internal.impl.DefaultArtifactResolver#resolve
关键代码:
private List<ArtifactResult> resolve( RepositorySystemSession session,Collection<? extends ArtifactRequest> requests )throws ArtifactResolutionException{ List<ArtifactResult> results = new ArrayList<>( requests.size() ); boolean failures = false; LocalRepositoryManager lrm = session.getLocalRepositoryManager(); WorkspaceReader workspace = session.getWorkspaceReader(); List<ResolutionGroup> groups = new ArrayList<>(); for ( ArtifactRequest request : requests ) { // 循环处理坐标请求 RequestTrace trace = RequestTrace.newChild( request.getTrace(), request ); ArtifactResult result = new ArtifactResult( request ); results.add( result ); Artifact artifact = request.getArtifact(); List<RemoteRepository> repos = request.getRepositories(); // 获取可用的仓库或镜像: 问题: 这个列表是如何获解析出来的 artifactResolving( session, trace, artifact ); String localPath = artifact.getProperty( ArtifactProperties.LOCAL_PATH, null ); if ( localPath != null ) { continue; } // 1. 处理版本 VersionResult versionResult; // 版本结果 try { VersionRequest versionRequest=new VersionRequest( artifact, repos, request.getRequestContext()); versionRequest.setTrace( trace ); versionResult = versionResolver.resolveVersion( session, versionRequest ); } catch ( VersionResolutionException e ) { continue; } artifact = artifact.setVersion( versionResult.getVersion()); // 设置版本 if ( versionResult.getRepository() != null ) { if ( versionResult.getRepository() instanceof RemoteRepository ) { repos = Collections.singletonList( (RemoteRepository) versionResult.getRepository() ); } else { repos = Collections.emptyList(); } } if ( workspace != null ) { File file = workspace.findArtifact( artifact ); // 工作空间查找 if ( file != null ) { // 找到提前结束 artifact = artifact.setFile( file ); result.setArtifact( artifact ); result.setRepository( workspace.getRepository() ); artifactResolved( session, trace, artifact, result.getRepository(), null ); continue; } } LocalArtifactResult local =lrm.find( session, new LocalArtifactRequest( artifact, repos, request.getRequestContext() ) ); // 本地查找 if ( isLocallyInstalled( local, versionResult ) ){ } else if ( local.getFile() != null ) { LOGGER.debug( "Verifying availability of {} from {}", local.getFile(), repos ); } // 核心: 远程查找 LOGGER.debug( "Resolving artifact {} from {}", artifact, repos ); AtomicBoolean resolved = new AtomicBoolean( false ); Iterator<ResolutionGroup> groupIt = groups.iterator(); // 这个group初始是没有值得,是一个缓存的作用 for ( RemoteRepository repo : repos ) { if ( !repo.getPolicy( artifact.isSnapshot() ).isEnabled() ) { continue; } try { Utils.checkOffline( session, offlineController, repo ); } catch ( RepositoryOfflineException e ) { result.addException( exception ); continue; } ResolutionGroup group = null; while ( groupIt.hasNext() ) { // 第一次进来不进入这里 ResolutionGroup t = groupIt.next(); if ( t.matches( repo ) ) { group = t; break; } } if ( group == null ) { // 第一次执行这里 group = new ResolutionGroup( repo ); // 设置仓库地址 groups.add( group ); groupIt = Collections.<ResolutionGroup>emptyList().iterator(); } // 加入条目 group.items.add( new ResolutionItem( trace, artifact, resolved, result, local, repo ) ); } } for ( ResolutionGroup group : groups ){ performDownloads( session, group ); // 执行下载的 } for ( ArtifactResult result : results ) { ArtifactRequest request = result.getRequest(); Artifact artifact = result.getArtifact(); if ( artifact == null || artifact.getFile() == null ) { failures = true; if ( result.getExceptions().isEmpty() ) { Exception exception = new ArtifactNotFoundException( request.getArtifact(), null ); result.addException( exception ); } RequestTrace trace = RequestTrace.newChild( request.getTrace(), request ); artifactResolved( session, trace, request.getArtifact(), null, result.getExceptions() ); } } if ( failures ) { throw new ArtifactResolutionException( results ); } return results; }
这里有个ResolutionGroup类
static class ResolutionGroup { final RemoteRepository repository; // 远程仓库 final List<ResolutionItem> items = new ArrayList<>(); ResolutionGroup( RemoteRepository repository ){ this.repository = repository; } boolean matches( RemoteRepository repo ) { return repository.getUrl().equals( repo.getUrl() ) && repository.getContentType().equals( repo.getContentType() ) && repository.isRepositoryManager() == repo.isRepositoryManager(); } }
-
org.eclipse.aether.internal.impl.DefaultArtifactResolver#gatherDownloads
一个条目对应一个远程仓库的选择
private List<ArtifactDownload> gatherDownloads( RepositorySystemSession session, ResolutionGroup group ) { LocalRepositoryManager lrm = session.getLocalRepositoryManager(); List<ArtifactDownload> downloads = new ArrayList<>(); for ( ResolutionItem item : group.items ) { Artifact artifact = item.artifact; if ( item.resolved.get() ) { // return value != 0; 这是一个开关, 具体作用暂时不知道 // resolved in previous resolution group continue; } ArtifactDownload download = new ArtifactDownload(); download.setArtifact( artifact ); download.setRequestContext( item.request.getRequestContext() ); download.setListener( SafeTransferListener.wrap( session ) ); download.setTrace( item.trace ); if ( item.local.getFile() != null ) { download.setFile( item.local.getFile() ); download.setExistenceCheck( true ); } else { String path = lrm.getPathForRemoteArtifact( artifact, group.repository, item.request.getRequestContext() ); download.setFile( new File( lrm.getRepository().getBasedir(), path ) ); } boolean snapshot = artifact.isSnapshot(); RepositoryPolicy policy = remoteRepositoryManager.getPolicy( session, group.repository, !snapshot, snapshot ); int errorPolicy = Utils.getPolicy( session, artifact, group.repository ); if ( ( errorPolicy & ResolutionErrorPolicy.CACHE_ALL ) != 0 ) { UpdateCheck<Artifact, ArtifactTransferException> check = new UpdateCheck<>(); check.setItem( artifact ); check.setFile( download.getFile() ); check.setFileValid( false ); check.setRepository( group.repository ); check.setPolicy( policy.getUpdatePolicy() ); item.updateCheck = check; updateCheckManager.checkArtifact( session, check ); if ( !check.isRequired() ) { item.result.addException( check.getException() ); continue; } } download.setChecksumPolicy( policy.getChecksumPolicy() ); download.setRepositories( item.repository.getMirroredRepositories() ); downloads.add( download ); item.download = download; } return downloads; // 返回下载的依赖 }
插件执行
执行方法org.apache.maven.plugin.DefaultBuildPluginManager#executeMojo,调用Mojo(一个goal对应一个Mojo)能力,执行org.apache.maven.plugin.MavenPluginManager#getConfiguredMojo获得Mojo实例执行org.apache.maven.plugin.Mojo#execute执行扩展插件的实现,至此,构建脱离公共流程,进入插件构建运行阶段
org.apache.maven.plugin.DefaultBuildPluginManager#executeMojo
public void executeMojo(MavenSession session, MojoExecution mojoExecution)
throws MojoFailureException, MojoExecutionException, PluginConfigurationException, PluginManagerException {
MavenProject project = session.getCurrentProject();
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
Mojo mojo = null;
ClassRealm pluginRealm;
try {
pluginRealm = getPluginRealm(session, mojoDescriptor.getPluginDescriptor());
} catch (PluginResolutionException e) {
throw new PluginExecutionException(mojoExecution, project, e);
}
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(pluginRealm);
MavenSession oldSession = legacySupport.getSession();
scope.enter();
try {
scope.seed(MavenProject.class, project);
scope.seed(MojoExecution.class, mojoExecution);
mojo = mavenPluginManager.getConfiguredMojo(Mojo.class, session, mojoExecution);
legacySupport.setSession(session);
try {
MojoExecutionEvent mojoExecutionEvent = new MojoExecutionEvent(session, project, mojoExecution, mojo);
mojoExecutionListener.beforeMojoExecution(mojoExecutionEvent);
mojo.execute(); // 执行不同的mojo, 例如 CleanMojo
mojoExecutionListener.afterMojoExecutionSuccess(mojoExecutionEvent);
} catch {
throw new PluginExecutionException(mojoExecution, project, e);
}
} catch (PluginContainerException e) {
} finally {
}
}
进入执行逻辑
mojo.execute(); // 不同mojo执行逻辑不同