diff --git a/maven-core/pom.xml b/maven-core/pom.xml
index 764050bde790..d0eb50439915 100644
--- a/maven-core/pom.xml
+++ b/maven-core/pom.xml
@@ -163,6 +163,11 @@ under the License.
mockito-core
test
+
+ org.mockito
+ mockito-junit-jupiter
+ test
+
org.junit.jupiter
junit-jupiter-api
diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/PluginDescriptorRequirementsValidator.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/PluginDescriptorRequirementsValidator.java
new file mode 100644
index 000000000000..e18914906195
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/PluginDescriptorRequirementsValidator.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.plugin.internal;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.PluginValidationManager;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Verify that plugin descriptor does not contain Plexus Component requirements.
+ *
+ * @since 3.10.0
+ */
+@Singleton
+@Named
+class PluginDescriptorRequirementsValidator implements MavenPluginConfigurationValidator {
+
+ private final PluginValidationManager pluginValidationManager;
+
+ @Inject
+ PluginDescriptorRequirementsValidator(PluginValidationManager pluginValidationManager) {
+ this.pluginValidationManager = requireNonNull(pluginValidationManager);
+ }
+
+ @Override
+ public void validate(
+ MavenSession mavenSession,
+ MojoDescriptor mojoDescriptor,
+ Class> mojoClass,
+ PlexusConfiguration pomConfiguration,
+ ExpressionEvaluator expressionEvaluator) {
+ if (!mojoDescriptor.getRequirements().isEmpty()) {
+ pluginValidationManager.reportPluginMojoValidationIssue(
+ PluginValidationManager.IssueLocality.EXTERNAL,
+ mavenSession,
+ mojoDescriptor,
+ mojoClass,
+ "Plugin uses Plexus Component requirements (@Component annotation). "
+ + "Use Maven 4 Dependency Injection (for v4 plugins) or JSR 330 annotations (for v3 plugins) to inject dependencies instead.");
+ }
+ }
+}
diff --git a/maven-core/src/test/java/org/apache/maven/plugin/internal/PluginDescriptorRequirementsValidatorTest.java b/maven-core/src/test/java/org/apache/maven/plugin/internal/PluginDescriptorRequirementsValidatorTest.java
new file mode 100644
index 000000000000..5e08558b0e30
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/plugin/internal/PluginDescriptorRequirementsValidatorTest.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.plugin.internal;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.PluginValidationManager;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.codehaus.plexus.component.repository.ComponentRequirement;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.contains;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+@ExtendWith(MockitoExtension.class)
+public class PluginDescriptorRequirementsValidatorTest {
+
+ @Mock
+ private PluginValidationManager pluginValidationManager;
+
+ @Mock
+ private MavenSession mavenSession;
+
+ @InjectMocks
+ private PluginDescriptorRequirementsValidator validator;
+
+ private final Class> mojoClass = PluginDescriptorRequirementsValidatorTest.class;
+
+ @Test
+ public void testValidateReportsIssueWhenMojoHasRequirements() {
+ MojoDescriptor mojoDescriptor = new MojoDescriptor();
+ mojoDescriptor.addRequirement(new ComponentRequirement());
+
+ validator.validate(mavenSession, mojoDescriptor, mojoClass, null, null);
+
+ verify(pluginValidationManager)
+ .reportPluginMojoValidationIssue(
+ eq(PluginValidationManager.IssueLocality.EXTERNAL),
+ eq(mavenSession),
+ eq(mojoDescriptor),
+ eq(mojoClass),
+ contains("Plugin uses Plexus Component requirements"));
+ }
+
+ @Test
+ public void testValidateDoesNotReportIssueWhenMojoHasNoRequirements() {
+ MojoDescriptor mojoDescriptor = new MojoDescriptor();
+
+ validator.validate(mavenSession, mojoDescriptor, mojoClass, null, null);
+
+ verify(pluginValidationManager, never())
+ .reportPluginMojoValidationIssue(
+ any(PluginValidationManager.IssueLocality.class),
+ any(MavenSession.class),
+ any(MojoDescriptor.class),
+ any(Class.class),
+ any(String.class));
+ }
+}
diff --git a/pom.xml b/pom.xml
index eb7f74274106..d0e550a86cac 100644
--- a/pom.xml
+++ b/pom.xml
@@ -497,6 +497,12 @@ under the License.
${mockitoVersion}
test
+
+ org.mockito
+ mockito-junit-jupiter
+ ${mockitoVersion}
+ test
+
org.xmlunit
xmlunit-core