diff --git a/core/lib/Drupal/Core/Plugin/Discovery/AttributeDiscoveryWithAnnotations.php b/core/lib/Drupal/Core/Plugin/Discovery/AttributeDiscoveryWithAnnotations.php
index e4d2a51a8533b123d0cbe699f45f17ff4c3067d1..a54e86087552fbb9444604830c9e948e019edb52 100644
--- a/core/lib/Drupal/Core/Plugin/Discovery/AttributeDiscoveryWithAnnotations.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/AttributeDiscoveryWithAnnotations.php
@@ -114,7 +114,7 @@ protected function parseClass(string $class, \SplFileInfo $fileinfo): array {
    * @see \Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery::prepareAnnotationDefinition()
    * @see \Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery::prepareAnnotationDefinition()
    */
-  protected function prepareAnnotationDefinition(AnnotationInterface $annotation, string $class): void {
+  private function prepareAnnotationDefinition(AnnotationInterface $annotation, string $class): void {
     $annotation->setClass($class);
     if (!$annotation->getProvider()) {
       $annotation->setProvider($this->getProviderFromNamespace($class));
@@ -133,7 +133,7 @@ protected function prepareAnnotationDefinition(AnnotationInterface $annotation,
    * @see \Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery::getAnnotationReader()
    * @see \Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery::getAnnotationReader()
    */
-  protected function getAnnotationReader() : SimpleAnnotationReader {
+  private function getAnnotationReader() : SimpleAnnotationReader {
     if (!isset($this->annotationReader)) {
       $this->annotationReader = new SimpleAnnotationReader();
 
diff --git a/core/modules/book/src/Plugin/migrate/destination/Book.php b/core/modules/book/src/Plugin/migrate/destination/Book.php
index 2f4ea33490660065bb02e2b8eab863d6d67c1865..dcc5056c89af907650b90e5b02d5bb2df8531456 100644
--- a/core/modules/book/src/Plugin/migrate/destination/Book.php
+++ b/core/modules/book/src/Plugin/migrate/destination/Book.php
@@ -3,14 +3,15 @@
 namespace Drupal\book\Plugin\migrate\destination;
 
 use Drupal\Core\Entity\EntityInterface;
-use Drupal\migrate\Attribute\MigrateDestination;
 use Drupal\migrate\Plugin\migrate\destination\EntityContentBase;
 use Drupal\migrate\Row;
 
 /**
- * Provides migrate destination plugin for Book content.
+ * @MigrateDestination(
+ *   id = "book",
+ *   provider = "book"
+ * )
  */
-#[MigrateDestination('book')]
 class Book extends EntityContentBase {
 
   /**
diff --git a/core/modules/datetime/src/Plugin/migrate/field/DateField.php b/core/modules/datetime/src/Plugin/migrate/field/DateField.php
index 9bfa3572e31e76774d86b4fa917e847eda5e923d..f6a33434d15bc057aee6650d7e43c49d0bb45699 100644
--- a/core/modules/datetime/src/Plugin/migrate/field/DateField.php
+++ b/core/modules/datetime/src/Plugin/migrate/field/DateField.php
@@ -6,25 +6,25 @@
 use Drupal\migrate\Plugin\MigrationInterface;
 use Drupal\migrate\MigrateException;
 use Drupal\migrate\Row;
-use Drupal\migrate_drupal\Attribute\MigrateField;
 use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
 
 // cspell:ignore todate
 
 /**
  * Provides a field plugin for date and time fields.
+ *
+ * @MigrateField(
+ *   id = "datetime",
+ *   type_map = {
+ *     "date" = "datetime",
+ *     "datestamp" =  "timestamp",
+ *     "datetime" =  "datetime",
+ *   },
+ *   core = {6,7},
+ *   source_module = "date",
+ *   destination_module = "datetime"
+ * )
  */
-#[MigrateField(
-  id: 'datetime',
-  core: [6, 7],
-  type_map: [
-    'date' => 'datetime',
-    'datestamp' => 'timestamp',
-    'datetime' => 'datetime',
-  ],
-  source_module: 'date',
-  destination_module: 'datetime',
-)]
 class DateField extends FieldPluginBase {
 
   /**
diff --git a/core/modules/file/src/Plugin/migrate/destination/EntityFile.php b/core/modules/file/src/Plugin/migrate/destination/EntityFile.php
index c953a71869a9e98fae3f1e93d80b24d7edfbfb4e..08b946f53f9abdc20baaaaecc9183163a959a8a0 100644
--- a/core/modules/file/src/Plugin/migrate/destination/EntityFile.php
+++ b/core/modules/file/src/Plugin/migrate/destination/EntityFile.php
@@ -3,15 +3,15 @@
 namespace Drupal\file\Plugin\migrate\destination;
 
 use Drupal\Core\Field\Plugin\Field\FieldType\UriItem;
-use Drupal\migrate\Attribute\MigrateDestination;
 use Drupal\migrate\Row;
 use Drupal\migrate\MigrateException;
 use Drupal\migrate\Plugin\migrate\destination\EntityContentBase;
 
 /**
- * Provides migrate destination plugin for File entities.
+ * @MigrateDestination(
+ *   id = "entity:file"
+ * )
  */
-#[MigrateDestination('entity:file')]
 class EntityFile extends EntityContentBase {
 
   /**
diff --git a/core/modules/migrate/migrate.api.php b/core/modules/migrate/migrate.api.php
index 9b3ab67bb980ae1aa8361eaee32d9756020b2a39..0339475ff0f79f3b9bc04870a9495a37fdbb6950 100644
--- a/core/modules/migrate/migrate.api.php
+++ b/core/modules/migrate/migrate.api.php
@@ -47,8 +47,8 @@
  * @section sec_source Migrate API source plugins
  * Migrate API source plugins implement
  * \Drupal\migrate\Plugin\MigrateSourceInterface and usually extend
- * \Drupal\migrate\Plugin\migrate\source\SourcePluginBase. They have the
- * \Drupal\migrate\Attribute\MigrateSource attribute and must be in
+ * \Drupal\migrate\Plugin\migrate\source\SourcePluginBase. They are annotated
+ * with \Drupal\migrate\Annotation\MigrateSource annotation and must be in
  * namespace subdirectory 'Plugin\migrate\source' under the namespace of the
  * module that defines them. Migrate API source plugins are managed by the
  * \Drupal\migrate\Plugin\MigrateSourcePluginManager class.
@@ -59,8 +59,8 @@
  * @section sec_process Migrate API process plugins
  * Migrate API process plugins implement
  * \Drupal\migrate\Plugin\MigrateProcessInterface and usually extend
- * \Drupal\migrate\ProcessPluginBase. They have the
- * \Drupal\migrate\Attribute\MigrateProcess attribute and must be in
+ * \Drupal\migrate\ProcessPluginBase. They are annotated with
+ * \Drupal\migrate\Annotation\MigrateProcessPlugin annotation and must be in
  * namespace subdirectory 'Plugin\migrate\process' under the namespace of the
  * module that defines them. Migrate API process plugins are managed by the
  * \Drupal\migrate\Plugin\MigratePluginManager class.
@@ -70,11 +70,12 @@
  * @section sec_destination Migrate API destination plugins
  * Migrate API destination plugins implement
  * \Drupal\migrate\Plugin\MigrateDestinationInterface and usually extend
- * \Drupal\migrate\Plugin\migrate\destination\DestinationBase. They have the
- * \Drupal\migrate\Attribute\MigrateDestination attribute and must be in
- * namespace subdirectory 'Plugin\migrate\destination' under the namespace of
- * the module that defines them. Migrate API destination plugins are managed by
- * the \Drupal\migrate\Plugin\MigrateDestinationPluginManager class.
+ * \Drupal\migrate\Plugin\migrate\destination\DestinationBase. They are
+ * annotated with \Drupal\migrate\Annotation\MigrateDestination annotation and
+ * must be in namespace subdirectory 'Plugin\migrate\destination' under the
+ * namespace of the module that defines them. Migrate API destination plugins
+ * are managed by the \Drupal\migrate\Plugin\MigrateDestinationPluginManager
+ * class.
  *
  * @link https://api.drupal.org/api/drupal/namespace/Drupal!migrate!Plugin!migrate!destination List of destination plugins for Drupal configuration and content entities provided by the core Migrate module. @endlink
  *
diff --git a/core/modules/migrate/migrate.services.yml b/core/modules/migrate/migrate.services.yml
index b7068cf68250a375e3f099d2969baaaba2557dc6..d7ef2ded4b0db0a2601a128c46174bc80ea73491 100644
--- a/core/modules/migrate/migrate.services.yml
+++ b/core/modules/migrate/migrate.services.yml
@@ -14,13 +14,7 @@ services:
     arguments: [source, '@container.namespaces', '@cache.discovery', '@module_handler']
   plugin.manager.migrate.process:
     class: Drupal\migrate\Plugin\MigratePluginManager
-    arguments:
-      - process
-      - '@container.namespaces'
-      - '@cache.discovery'
-      - '@module_handler'
-      - 'Drupal\migrate\Attribute\MigrateProcess'
-      - 'Drupal\migrate\Annotation\MigrateProcessPlugin'
+    arguments: [process, '@container.namespaces', '@cache.discovery', '@module_handler', 'Drupal\migrate\Annotation\MigrateProcessPlugin']
   plugin.manager.migrate.destination:
     class: Drupal\migrate\Plugin\MigrateDestinationPluginManager
     arguments: [destination, '@container.namespaces', '@cache.discovery', '@module_handler', '@entity_type.manager']
diff --git a/core/modules/migrate/src/Attribute/MigrateDestination.php b/core/modules/migrate/src/Attribute/MigrateDestination.php
deleted file mode 100644
index 54e469b1381452ba1e0814a8ad69ae08a58dd707..0000000000000000000000000000000000000000
--- a/core/modules/migrate/src/Attribute/MigrateDestination.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\migrate\Attribute;
-
-use Drupal\Component\Plugin\Attribute\Plugin;
-
-/**
- * Defines a MigrateDestination attribute.
- *
- * Plugin Namespace: Plugin\migrate\destination
- *
- * For a working example, see
- * \Drupal\migrate\Plugin\migrate\destination\UrlAlias
- *
- * @see \Drupal\migrate\Plugin\MigrateDestinationPluginManager
- * @see \Drupal\migrate\Plugin\MigrateDestinationInterface
- * @see \Drupal\migrate\Plugin\migrate\destination\DestinationBase
- * @see \Drupal\migrate\Attribute\MigrateProcess
- * @see \Drupal\migrate\Attribute\MigrateSource
- * @see plugin_api
- *
- * @ingroup migration
- */
-#[\Attribute(\Attribute::TARGET_CLASS)]
-class MigrateDestination extends Plugin {
-
-  /**
-   * Constructs a migrate destination plugin attribute object.
-   *
-   * @param string $id
-   *   A unique identifier for the destination plugin.
-   * @param bool $requirements_met
-   *   (optional) Whether requirements are met.
-   * @param string|null $destination_module
-   *   (optional) Identifies the system handling the data the destination plugin
-   *   will write. The destination plugin itself determines how the value is
-   *   used. For example, Migrate's destination plugins expect
-   *   destination_module to be the name of a module that must be installed on
-   *   the destination.
-   * @param class-string|null $deriver
-   *   (optional) The deriver class.
-   */
-  public function __construct(
-    public readonly string $id,
-    public bool $requirements_met = TRUE,
-    public readonly ?string $destination_module = NULL,
-    public readonly ?string $deriver = NULL,
-  ) {
-  }
-
-}
diff --git a/core/modules/migrate/src/Attribute/MigrateProcess.php b/core/modules/migrate/src/Attribute/MigrateProcess.php
deleted file mode 100644
index ba2cb65cd147767ae969c7870fc5aaf47926d8b4..0000000000000000000000000000000000000000
--- a/core/modules/migrate/src/Attribute/MigrateProcess.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\migrate\Attribute;
-
-use Drupal\Component\Plugin\Attribute\Plugin;
-
-/**
- * Defines a MigrateProcess attribute.
- *
- * Plugin Namespace: Plugin\migrate\process
- *
- * For a working example, see
- * \Drupal\migrate\Plugin\migrate\process\DefaultValue
- *
- * @see \Drupal\migrate\Plugin\MigratePluginManager
- * @see \Drupal\migrate\Plugin\MigrateProcessInterface
- * @see \Drupal\migrate\ProcessPluginBase
- * @see \Drupal\migrate\Attribute\MigrateDestination
- * @see \Drupal\migrate\Attribute\MigrateSource
- * @see plugin_api
- *
- * @ingroup migration
- */
-#[\Attribute(\Attribute::TARGET_CLASS)]
-class MigrateProcess extends Plugin {
-
-  /**
-   * Constructs a migrate process plugin attribute object.
-   *
-   * @param string $id
-   *   A unique identifier for the process plugin.
-   * @param bool $handle_multiples
-   *   (optional) Whether the plugin handles multiples itself. Typically these
-   *   plugins will expect an array as input and iterate over it themselves,
-   *   changing the whole array. For example the 'sub_process' and the 'flatten'
-   *   plugins. If the plugin only needs to change a single value, then it can
-   *   skip setting this attribute and let
-   *   \Drupal\migrate\MigrateExecutable::processRow() handle the iteration.
-   * @param class-string|null $deriver
-   *   (optional) The deriver class.
-   */
-  public function __construct(
-    public readonly string $id,
-    public readonly bool $handle_multiples = FALSE,
-    public readonly ?string $deriver = NULL,
-  ) {}
-
-}
diff --git a/core/modules/migrate/src/Attribute/MigrateSource.php b/core/modules/migrate/src/Attribute/MigrateSource.php
deleted file mode 100644
index 1dd69003506315bcefa9713d9debb80b724da471..0000000000000000000000000000000000000000
--- a/core/modules/migrate/src/Attribute/MigrateSource.php
+++ /dev/null
@@ -1,93 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\migrate\Attribute;
-
-use Drupal\Component\Plugin\Attribute\Plugin;
-
-/**
- * Defines a MigrateSource attribute.
- *
- * Plugin Namespace: Plugin\migrate\source
- *
- * For a working example, see
- * \Drupal\migrate\Plugin\migrate\source\EmptySource
- * \Drupal\migrate_drupal\Plugin\migrate\source\UrlAlias
- *
- * @see \Drupal\migrate\Plugin\MigratePluginManager
- * @see \Drupal\migrate\Plugin\MigrateSourceInterface
- * @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
- * @see \Drupal\migrate\Attribute\MigrateDestination
- * @see \Drupal\migrate\Attribute\MigrateProcess
- * @see plugin_api
- *
- * @ingroup migration
- */
-#[\Attribute(\Attribute::TARGET_CLASS)]
-class MigrateSource extends Plugin implements MultipleProviderAttributeInterface {
-
-  /**
-   * The providers of the source plugin.
-   */
-  protected array $providers = [];
-
-  /**
-   * Constructs a migrate source plugin attribute object.
-   *
-   * @param string $id
-   *   A unique identifier for the source plugin.
-   * @param string $source_module
-   *   Identifies the system providing the data the source plugin will read.
-   * @param bool $requirements_met
-   *   (optional) Whether requirements are met. Defaults to true. The source
-   *   plugin itself determines how the value is used. For example, Migrate
-   *   Drupal's source plugins expect source_module to be the name of a module
-   *   that must be installed and enabled in the source database.
-   * @param mixed $minimum_version
-   *   (optional) Specifies the minimum version of the source provider. This can
-   *   be any type, and the source plugin itself determines how it is used. For
-   *   example, Migrate Drupal's source plugins expect this to be an integer
-   *   representing the minimum installed database schema version of the module
-   *   specified by source_module.
-   * @param class-string|null $deriver
-   *   (optional) The deriver class.
-   *
-   * @see \Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase::checkRequirements
-   */
-  public function __construct(
-    public readonly string $id,
-    public readonly string $source_module,
-    public bool $requirements_met = TRUE,
-    public readonly mixed $minimum_version = '',
-    public readonly ?string $deriver = NULL,
-  ) {}
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setProvider(string $provider): void {
-    $this->setProviders([$provider]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getProviders(): array {
-    return $this->providers;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setProviders(array $providers): void {
-    if ($providers) {
-      parent::setProvider(reset($providers));
-    }
-    else {
-      $this->provider = NULL;
-    }
-    $this->providers = $providers;
-  }
-
-}
diff --git a/core/modules/migrate/src/Attribute/MultipleProviderAttributeInterface.php b/core/modules/migrate/src/Attribute/MultipleProviderAttributeInterface.php
deleted file mode 100644
index 437ddfb8b9aeb28d5ff5ff17929e94ebf4208a6b..0000000000000000000000000000000000000000
--- a/core/modules/migrate/src/Attribute/MultipleProviderAttributeInterface.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\migrate\Attribute;
-
-use Drupal\Component\Plugin\Attribute\AttributeInterface;
-
-/**
- * Defines a common interface for attributes with multiple providers.
- *
- * @internal
- *   This is a temporary solution to the fact that migration source plugins have
- *   more than one provider. This functionality will be moved to core in
- *   https://www.drupal.org/node/2786355.
- */
-interface MultipleProviderAttributeInterface extends AttributeInterface {
-
-  /**
-   * Gets the name of the provider of the attribute class.
-   *
-   * @return string|null
-   *   The provider of the attribute. If there are multiple providers the first
-   *   is returned.
-   */
-  public function getProvider(): ?string;
-
-  /**
-   * Gets the provider names of the attribute class.
-   *
-   * @return string[]
-   *   The providers of the attribute.
-   */
-  public function getProviders(): array;
-
-  /**
-   * Sets the provider names of the attribute class.
-   *
-   * @param string[] $providers
-   *   The providers of the attribute.
-   */
-  public function setProviders(array $providers): void;
-
-}
diff --git a/core/modules/migrate/src/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php b/core/modules/migrate/src/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php
index edea32fefda2e16ccd2cd2e8fdf7b4e3188325c9..c51468911645ccba693d079be7126bddec93fa50 100644
--- a/core/modules/migrate/src/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php
+++ b/core/modules/migrate/src/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php
@@ -3,10 +3,12 @@
 namespace Drupal\migrate\Plugin\Discovery;
 
 use Doctrine\Common\Annotations\AnnotationRegistry;
+use Drupal\Component\Annotation\AnnotationInterface;
 use Drupal\Component\Annotation\Doctrine\StaticReflectionParser as BaseStaticReflectionParser;
 use Drupal\Component\Annotation\Reflection\MockFileFinder;
 use Drupal\Component\ClassFinder\ClassFinder;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
+use Drupal\migrate\Annotation\MultipleProviderAnnotationInterface;
 
 /**
  * Determines providers based on a class's and its parent's namespaces.
@@ -18,7 +20,12 @@
  */
 class AnnotatedClassDiscoveryAutomatedProviders extends AnnotatedClassDiscovery {
 
-  use AnnotatedDiscoveryAutomatedProvidersTrait;
+  /**
+   * A utility object that can use active autoloaders to find files for classes.
+   *
+   * @var \Drupal\Component\ClassFinder\ClassFinderInterface
+   */
+  protected $finder;
 
   /**
    * Constructs an AnnotatedClassDiscoveryAutomatedProviders object.
@@ -41,6 +48,26 @@ public function __construct($subdir, \Traversable $root_namespaces, $plugin_defi
     $this->finder = new ClassFinder();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function prepareAnnotationDefinition(AnnotationInterface $annotation, $class, BaseStaticReflectionParser $parser = NULL) {
+    if (!($annotation instanceof MultipleProviderAnnotationInterface)) {
+      throw new \LogicException('AnnotatedClassDiscoveryAutomatedProviders annotations must implement \Drupal\migrate\Annotation\MultipleProviderAnnotationInterface');
+    }
+    $annotation->setClass($class);
+    $providers = $annotation->getProviders();
+    // Loop through all the parent classes and add their providers (which we
+    // infer by parsing their namespaces) to the $providers array.
+    do {
+      $providers[] = $this->getProviderFromNamespace($parser->getNamespaceName());
+    } while ($parser = StaticReflectionParser::getParentParser($parser, $this->finder));
+    $providers = array_unique(array_filter($providers, function ($provider) {
+      return $provider && $provider !== 'component';
+    }));
+    $annotation->setProviders($providers);
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/migrate/src/Plugin/Discovery/AnnotatedDiscoveryAutomatedProvidersTrait.php b/core/modules/migrate/src/Plugin/Discovery/AnnotatedDiscoveryAutomatedProvidersTrait.php
deleted file mode 100644
index aa9d8745a677f9767347b3ca32507a6a1a3b08da..0000000000000000000000000000000000000000
--- a/core/modules/migrate/src/Plugin/Discovery/AnnotatedDiscoveryAutomatedProvidersTrait.php
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-
-namespace Drupal\migrate\Plugin\Discovery;
-
-use Drupal\Component\Annotation\AnnotationInterface;
-use Drupal\Component\Annotation\Doctrine\StaticReflectionParser as BaseStaticReflectionParser;
-use Drupal\migrate\Annotation\MultipleProviderAnnotationInterface;
-
-/**
- * Provides method for annotation discovery with multiple providers.
- */
-trait AnnotatedDiscoveryAutomatedProvidersTrait {
-
-  /**
-   * A utility object that can use active autoloaders to find files for classes.
-   *
-   * @var \Drupal\Component\ClassFinder\ClassFinderInterface
-   */
-  protected $finder;
-
-  /**
-   * Prepares the annotation definition.
-   *
-   * This is modified from the prepareAnnotationDefinition method from annotated
-   * class discovery to account for multiple providers.
-   *
-   * @param \Drupal\Component\Annotation\AnnotationInterface $annotation
-   *   The annotation derived from the plugin.
-   * @param class-string $class
-   *   The class used for the plugin.
-   * @param \Drupal\Component\Annotation\Doctrine\StaticReflectionParser|null $parser
-   *   Static reflection parser.
-   *
-   * @see \Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery::prepareAnnotationDefinition()
-   * @see \Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery::prepareAnnotationDefinition()
-   */
-  protected function prepareAnnotationDefinition(AnnotationInterface $annotation, $class, ?BaseStaticReflectionParser $parser = NULL): void {
-    if (!($annotation instanceof MultipleProviderAnnotationInterface)) {
-      throw new \LogicException('AnnotatedClassDiscoveryAutomatedProviders annotations must implement ' . MultipleProviderAnnotationInterface::class);
-    }
-    if (!$parser) {
-      throw new \LogicException('Parser argument must be passed for automated providers discovery.');
-    }
-    if (!method_exists($this, 'getProviderFromNamespace')) {
-      throw new \LogicException('Classes using \Drupal\migrate\Plugin\Discovery\AnnotatedDiscoveryAutomatedProvidersTrait must have getProviderFromNamespace() method.');
-    }
-    // @see \Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery::prepareAnnotationDefinition()
-    $annotation->setClass($class);
-    $providers = $annotation->getProviders();
-    // Loop through all the parent classes and add their providers (which we
-    // infer by parsing their namespaces) to the $providers array.
-    do {
-      $providers[] = $this->getProviderFromNamespace($parser->getNamespaceName());
-    } while ($parser = StaticReflectionParser::getParentParser($parser, $this->finder));
-    $providers = array_diff(array_unique(array_filter($providers)), ['component']);
-    $annotation->setProviders($providers);
-  }
-
-}
diff --git a/core/modules/migrate/src/Plugin/Discovery/AttributeClassDiscoveryAutomatedProviders.php b/core/modules/migrate/src/Plugin/Discovery/AttributeClassDiscoveryAutomatedProviders.php
deleted file mode 100644
index c5691a57bf9e1a7ffb854f358637bb661baaff5b..0000000000000000000000000000000000000000
--- a/core/modules/migrate/src/Plugin/Discovery/AttributeClassDiscoveryAutomatedProviders.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\migrate\Plugin\Discovery;
-
-use Drupal\Component\Plugin\Attribute\AttributeInterface;
-use Drupal\Core\Plugin\Discovery\AttributeClassDiscovery;
-use Drupal\migrate\Attribute\MultipleProviderAttributeInterface;
-
-/**
- * Determines providers based on the namespaces of a class and its ancestors.
- *
- * @internal
- *   This is a temporary solution to the fact that migration source plugins have
- *   more than one provider. This functionality will be moved to core in
- *   https://www.drupal.org/node/2786355.
- */
-class AttributeClassDiscoveryAutomatedProviders extends AttributeClassDiscovery {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function prepareAttributeDefinition(AttributeInterface $attribute, string $class): void {
-    if (!($attribute instanceof MultipleProviderAttributeInterface)) {
-      throw new \LogicException('AttributeClassDiscoveryAutomatedProviders must implement ' . MultipleProviderAttributeInterface::class);
-    }
-    // @see Drupal\Component\Plugin\Discovery\AttributeClassDiscovery::prepareAttributeDefinition()
-    $attribute->setClass($class);
-
-    // Loop through all the parent classes and add their providers (which we
-    // infer by parsing their namespaces) to the $providers array.
-    $providers = $attribute->getProviders();
-    do {
-      $providers[] = $this->getProviderFromNamespace($class);
-    } while (($class = get_parent_class($class)) !== FALSE);
-
-    $providers = array_diff(array_unique(array_filter($providers)), ['component']);
-    $attribute->setProviders($providers);
-  }
-
-}
diff --git a/core/modules/migrate/src/Plugin/Discovery/AttributeDiscoveryWithAnnotationsAutomatedProviders.php b/core/modules/migrate/src/Plugin/Discovery/AttributeDiscoveryWithAnnotationsAutomatedProviders.php
deleted file mode 100644
index fab94bf307fecda495906fbd9db11b5850e716a2..0000000000000000000000000000000000000000
--- a/core/modules/migrate/src/Plugin/Discovery/AttributeDiscoveryWithAnnotationsAutomatedProviders.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\migrate\Plugin\Discovery;
-
-use Drupal\Component\Annotation\Doctrine\StaticReflectionParser as BaseStaticReflectionParser;
-use Drupal\Component\Annotation\Reflection\MockFileFinder;
-use Drupal\Component\ClassFinder\ClassFinder;
-use Drupal\Component\Plugin\Attribute\AttributeInterface;
-use Drupal\Core\Plugin\Discovery\AttributeDiscoveryWithAnnotations;
-
-/**
- * Enables both attribute and annotation discovery for plugin definitions.
- *
- * @internal
- *   This is a temporary solution to the fact that migration source plugins have
- *   more than one provider. This functionality will be moved to core in
- *   https://www.drupal.org/node/2786355.
- */
-class AttributeDiscoveryWithAnnotationsAutomatedProviders extends AttributeDiscoveryWithAnnotations {
-
-  use AnnotatedDiscoveryAutomatedProvidersTrait;
-
-  /**
-   * Instance of attribute class discovery with automatic providers.
-   *
-   * Since there isn't multiple inheritance, instantiate the attribute only
-   * discovery for code reuse.
-   *
-   * @var \Drupal\migrate\Plugin\Discovery\AttributeClassDiscoveryAutomatedProviders
-   */
-  private AttributeClassDiscoveryAutomatedProviders $attributeDiscovery;
-
-  public function __construct(
-    string $subdir,
-    \Traversable $rootNamespaces,
-    string $pluginDefinitionAttributeName = 'Drupal\Component\Plugin\Attribute\Plugin',
-    string $pluginDefinitionAnnotationName = 'Drupal\Component\Annotation\Plugin',
-    array $additionalNamespaces = [],
-  ) {
-    parent::__construct($subdir, $rootNamespaces, $pluginDefinitionAttributeName, $pluginDefinitionAnnotationName, $additionalNamespaces);
-    $this->finder = new ClassFinder();
-    $this->attributeDiscovery = new AttributeClassDiscoveryAutomatedProviders($subdir, $rootNamespaces, $pluginDefinitionAttributeName);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function prepareAttributeDefinition(AttributeInterface $attribute, string $class): void {
-    $this->attributeDiscovery->prepareAttributeDefinition($attribute, $class);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function parseClass(string $class, \SplFileInfo $fileinfo): array {
-    // The filename is already known, so there is no need to find the
-    // file. However, StaticReflectionParser needs a finder, so use a
-    // mock version.
-    $finder = MockFileFinder::create($fileinfo->getPathName());
-    $parser = new BaseStaticReflectionParser($class, $finder, FALSE);
-
-    $reflection_class = $parser->getReflectionClass();
-    // @todo Handle deprecating definitions discovery via annotations in
-    // https://www.drupal.org/project/drupal/issues/3265945.
-    /** @var \Drupal\Component\Annotation\AnnotationInterface $annotation */
-    if ($annotation = $this->getAnnotationReader()->getClassAnnotation($reflection_class, $this->pluginDefinitionAnnotationName)) {
-      $this->prepareAnnotationDefinition($annotation, $class, $parser);
-      return ['id' => $annotation->getId(), 'content' => $annotation->get()];
-    }
-
-    // Annotations use static reflection and are able to analyze a class that
-    // extends classes or uses traits that do not exist. Attribute discovery
-    // will trigger a fatal error with such classes, so only call it if the
-    // class has a class attribute.
-    if ($reflection_class->hasClassAttribute($this->pluginDefinitionAttributeName)) {
-      return parent::parseClass($class, $fileinfo);
-    }
-    return ['id' => NULL, 'content' => NULL];
-  }
-
-}
diff --git a/core/modules/migrate/src/Plugin/MigrateDestinationInterface.php b/core/modules/migrate/src/Plugin/MigrateDestinationInterface.php
index d2dbe2f68abd78b7c671ccd5729e2e8b4957e45e..d2c7fb7ee9947571214d39999fe0e1a60dff5ec7 100644
--- a/core/modules/migrate/src/Plugin/MigrateDestinationInterface.php
+++ b/core/modules/migrate/src/Plugin/MigrateDestinationInterface.php
@@ -13,7 +13,7 @@
  *
  * @see \Drupal\migrate\Plugin\migrate\destination\DestinationBase
  * @see \Drupal\migrate\Plugin\MigrateDestinationPluginManager
- * @see \Drupal\migrate\Attribute\MigrateDestination
+ * @see \Drupal\migrate\Annotation\MigrateDestination
  * @see plugin_api
  *
  * @ingroup migration
diff --git a/core/modules/migrate/src/Plugin/MigrateDestinationPluginManager.php b/core/modules/migrate/src/Plugin/MigrateDestinationPluginManager.php
index 6b7514435f2920478aafce228ad96065bfd11677..b65515c3afedb86ec18ea8993edb92ec24eab18d 100644
--- a/core/modules/migrate/src/Plugin/MigrateDestinationPluginManager.php
+++ b/core/modules/migrate/src/Plugin/MigrateDestinationPluginManager.php
@@ -5,14 +5,13 @@
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\migrate\Attribute\MigrateDestination;
 
 /**
  * Plugin manager for migrate destination plugins.
  *
  * @see \Drupal\migrate\Plugin\MigrateDestinationInterface
  * @see \Drupal\migrate\Plugin\migrate\destination\DestinationBase
- * @see \Drupal\migrate\Attribute\MigrateDestination
+ * @see \Drupal\migrate\Annotation\MigrateDestination
  * @see plugin_api
  *
  * @ingroup migration
@@ -41,15 +40,12 @@ class MigrateDestinationPluginManager extends MigratePluginManager {
    *   The module handler to invoke the alter hook with.
    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
    *   The entity type manager.
-   * @param string $attribute
-   *   (optional) The attribute class name. Defaults to
-   *   'Drupal\migrate\Attribute\MigrateDestination'.
    * @param string $annotation
    *   (optional) The annotation class name. Defaults to
    *   'Drupal\migrate\Annotation\MigrateDestination'.
    */
-  public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager, $attribute = MigrateDestination::class, $annotation = 'Drupal\migrate\Annotation\MigrateDestination') {
-    parent::__construct($type, $namespaces, $cache_backend, $module_handler, $attribute, $annotation);
+  public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager, $annotation = 'Drupal\migrate\Annotation\MigrateDestination') {
+    parent::__construct($type, $namespaces, $cache_backend, $module_handler, $annotation);
     $this->entityTypeManager = $entity_type_manager;
   }
 
diff --git a/core/modules/migrate/src/Plugin/MigratePluginManager.php b/core/modules/migrate/src/Plugin/MigratePluginManager.php
index 9eba756ab1be31715f37f0afc6dbb50cb1b17ca7..b3645dbdd0e41c3bbf3419dfb33bea71bdf8fc7c 100644
--- a/core/modules/migrate/src/Plugin/MigratePluginManager.php
+++ b/core/modules/migrate/src/Plugin/MigratePluginManager.php
@@ -2,8 +2,6 @@
 
 namespace Drupal\migrate\Plugin;
 
-use Drupal\Component\Plugin\Attribute\AttributeInterface;
-use Drupal\Component\Plugin\Attribute\PluginID;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -13,10 +11,10 @@
  * Manages migrate plugins.
  *
  * @see hook_migrate_info_alter()
- * @see \Drupal\migrate\Attribute\MigrateSource
+ * @see \Drupal\migrate\Annotation\MigrateSource
  * @see \Drupal\migrate\Plugin\MigrateSourceInterface
  * @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
- * @see \Drupal\migrate\Attribute\MigrateProcess
+ * @see \Drupal\migrate\Annotation\MigrateProcessPlugin
  * @see \Drupal\migrate\Plugin\MigrateProcessInterface
  * @see \Drupal\migrate\Plugin\migrate\process\ProcessPluginBase
  * @see plugin_api
@@ -38,20 +36,12 @@ class MigratePluginManager extends DefaultPluginManager implements MigratePlugin
    *   Cache backend instance to use.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler to invoke the alter hook with.
-   * @param string $attribute
-   *   (optional) The attribute class name. Defaults to
-   *   'Drupal\Component\Plugin\Attribute\PluginID'.
    * @param string $annotation
    *   (optional) The annotation class name. Defaults to
    *   'Drupal\Component\Annotation\PluginID'.
    */
-  public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, $attribute = PluginID::class, $annotation = 'Drupal\Component\Annotation\PluginID') {
-    if (!is_subclass_of($attribute, AttributeInterface::class)) {
-      // Backward compatibility.
-      $annotation = $attribute;
-      $attribute = PluginID::class;
-    }
-    parent::__construct("Plugin/migrate/$type", $namespaces, $module_handler, NULL, $attribute, $annotation);
+  public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, $annotation = 'Drupal\Component\Annotation\PluginID') {
+    parent::__construct("Plugin/migrate/$type", $namespaces, $module_handler, NULL, $annotation);
     $this->alterInfo('migrate_' . $type . '_info');
     $this->setCacheBackend($cache_backend, 'migrate_plugins_' . $type);
   }
diff --git a/core/modules/migrate/src/Plugin/MigrateProcessInterface.php b/core/modules/migrate/src/Plugin/MigrateProcessInterface.php
index 7d2d365d881718722568f54bcfc2e266f6e61b54..6b3832c89b6f28fab66ec79aa959184eff8e03d0 100644
--- a/core/modules/migrate/src/Plugin/MigrateProcessInterface.php
+++ b/core/modules/migrate/src/Plugin/MigrateProcessInterface.php
@@ -15,7 +15,7 @@
  *
  * @see \Drupal\migrate\Plugin\MigratePluginManager
  * @see \Drupal\migrate\ProcessPluginBase
- * @see \Drupal\migrate\Attribute\MigrateProcess
+ * @see \Drupal\migrate\Annotation\MigrateProcessPlugin
  * @see plugin_api
  *
  * @ingroup migration
diff --git a/core/modules/migrate/src/Plugin/MigrateSourceInterface.php b/core/modules/migrate/src/Plugin/MigrateSourceInterface.php
index b05236ad369adf239f28201ac03ef6134110f933..f33dc68cbc80f4719860d8c8bd6ffbe7a44f8948 100644
--- a/core/modules/migrate/src/Plugin/MigrateSourceInterface.php
+++ b/core/modules/migrate/src/Plugin/MigrateSourceInterface.php
@@ -9,7 +9,7 @@
  * Defines an interface for migrate sources.
  *
  * @see \Drupal\migrate\Plugin\MigratePluginManager
- * @see \Drupal\migrate\Attribute\MigrateSource
+ * @see \Drupal\migrate\Annotation\MigrateSource
  * @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
  * @see plugin_api
  *
diff --git a/core/modules/migrate/src/Plugin/MigrateSourcePluginManager.php b/core/modules/migrate/src/Plugin/MigrateSourcePluginManager.php
index 74fb59b5944781d0b707ba27246700fdb862b392..965da5dd766e49770b75ed347ffb933ca2b19972 100644
--- a/core/modules/migrate/src/Plugin/MigrateSourcePluginManager.php
+++ b/core/modules/migrate/src/Plugin/MigrateSourcePluginManager.php
@@ -4,10 +4,8 @@
 
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
 use Drupal\migrate\Plugin\Discovery\AnnotatedClassDiscoveryAutomatedProviders;
-use Drupal\migrate\Plugin\Discovery\AttributeClassDiscoveryAutomatedProviders;
-use Drupal\migrate\Plugin\Discovery\AttributeDiscoveryWithAnnotationsAutomatedProviders;
+use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
 use Drupal\migrate\Plugin\Discovery\ProviderFilterDecorator;
 
 /**
@@ -15,7 +13,7 @@
  *
  * @see \Drupal\migrate\Plugin\MigrateSourceInterface
  * @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
- * @see \Drupal\migrate\Attribute\MigrateSource
+ * @see \Drupal\migrate\Annotation\MigrateSource
  * @see plugin_api
  *
  * @ingroup migration
@@ -37,7 +35,7 @@ class MigrateSourcePluginManager extends MigratePluginManager {
    *   The module handler to invoke the alter hook with.
    */
   public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
-    parent::__construct($type, $namespaces, $cache_backend, $module_handler, 'Drupal\migrate\Attribute\MigrateSource', 'Drupal\migrate\Annotation\MigrateSource');
+    parent::__construct($type, $namespaces, $cache_backend, $module_handler, 'Drupal\migrate\Annotation\MigrateSource');
   }
 
   /**
@@ -45,30 +43,7 @@ public function __construct($type, \Traversable $namespaces, CacheBackendInterfa
    */
   protected function getDiscovery() {
     if (!$this->discovery) {
-      if (isset($this->pluginDefinitionAttributeName) && isset($this->pluginDefinitionAnnotationName)) {
-        $discovery = new AttributeDiscoveryWithAnnotationsAutomatedProviders(
-          $this->subdir,
-          $this->namespaces,
-          $this->pluginDefinitionAttributeName,
-          $this->pluginDefinitionAnnotationName,
-          $this->additionalAnnotationNamespaces,
-        );
-      }
-      elseif (isset($this->pluginDefinitionAttributeName)) {
-        $discovery = new AttributeClassDiscoveryAutomatedProviders(
-          $this->subdir,
-          $this->namespaces,
-          $this->pluginDefinitionAttributeName,
-        );
-      }
-      else {
-        $discovery = new AnnotatedClassDiscoveryAutomatedProviders(
-          $this->subdir,
-          $this->namespaces,
-          $this->pluginDefinitionAnnotationName,
-          $this->additionalAnnotationNamespaces,
-        );
-      }
+      $discovery = new AnnotatedClassDiscoveryAutomatedProviders($this->subdir, $this->namespaces, $this->pluginDefinitionAnnotationName, $this->additionalAnnotationNamespaces);
       $this->discovery = new ContainerDerivativeDiscoveryDecorator($discovery);
     }
     return $this->discovery;
diff --git a/core/modules/migrate/src/Plugin/migrate/destination/DestinationBase.php b/core/modules/migrate/src/Plugin/migrate/destination/DestinationBase.php
index 5712613e218bdd8353ff336deed264ce12ddc22e..4a7fc59d827049809449db427b392f576abd2834 100644
--- a/core/modules/migrate/src/Plugin/migrate/destination/DestinationBase.php
+++ b/core/modules/migrate/src/Plugin/migrate/destination/DestinationBase.php
@@ -21,7 +21,7 @@
  * information, refer to \Drupal\migrate\Plugin\MigrateDestinationInterface.
  *
  * @see \Drupal\migrate\Plugin\MigrateDestinationPluginManager
- * @see \Drupal\migrate\Attribute\MigrateDestination
+ * @see \Drupal\migrate\Annotation\MigrateDestination
  * @see plugin_api
  *
  * @ingroup migration
diff --git a/core/modules/migrate/src/Plugin/migrate/id_map/NullIdMap.php b/core/modules/migrate/src/Plugin/migrate/id_map/NullIdMap.php
index a6b2e3339e52333ff9240ad86d60189ac413865f..80c5da68a5a1e1d6814a2c9e6071dd6c432a590f 100644
--- a/core/modules/migrate/src/Plugin/migrate/id_map/NullIdMap.php
+++ b/core/modules/migrate/src/Plugin/migrate/id_map/NullIdMap.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\migrate\Plugin\migrate\id_map;
 
-use Drupal\Component\Plugin\Attribute\PluginID;
 use Drupal\Core\Plugin\PluginBase;
 use Drupal\migrate\MigrateMessageInterface;
 use Drupal\migrate\Plugin\MigrateIdMapInterface;
@@ -13,8 +12,9 @@
  * Defines the null ID map implementation.
  *
  * This serves as a dummy in order to not store anything.
+ *
+ * @PluginID("null")
  */
-#[PluginID('null')]
 class NullIdMap extends PluginBase implements MigrateIdMapInterface {
 
   /**
diff --git a/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php
index d66d3ce2fb2b34d291d8cb3308e9e22ad469d3d3..b9261d098943762007b561e63afa302b293de1ba 100644
--- a/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php
+++ b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\migrate\Plugin\migrate\id_map;
 
-use Drupal\Component\Plugin\Attribute\PluginID;
 use Drupal\Core\Database\DatabaseException;
 use Drupal\Core\Database\DatabaseExceptionWrapper;
 use Drupal\Core\Database\Exception\SchemaTableKeyTooLargeException;
@@ -31,8 +30,9 @@
  *
  * It creates one map and one message table per migration entity to store the
  * relevant information.
+ *
+ * @PluginID("sql")
  */
-#[PluginID('sql')]
 class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryPluginInterface, HighestIdInterface {
 
   /**
diff --git a/core/modules/migrate/src/Plugin/migrate/process/Explode.php b/core/modules/migrate/src/Plugin/migrate/process/Explode.php
index c6d9024926593e6c97d5802d2d37e35cd0c12415..38a58ed4a405e5ad374481707df3fdaca98a1094 100644
--- a/core/modules/migrate/src/Plugin/migrate/process/Explode.php
+++ b/core/modules/migrate/src/Plugin/migrate/process/Explode.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\migrate\Plugin\migrate\process;
 
-use Drupal\migrate\Attribute\MigrateProcess;
 use Drupal\migrate\ProcessPluginBase;
 use Drupal\migrate\MigrateException;
 use Drupal\migrate\MigrateExecutableInterface;
@@ -87,8 +86,11 @@
  * configuration, if foo is '', NULL or FALSE, then bar will be [].
  *
  * @see \Drupal\migrate\Plugin\MigrateProcessInterface
+ *
+ * @MigrateProcessPlugin(
+ *   id = "explode"
+ * )
  */
-#[MigrateProcess('explode')]
 class Explode extends ProcessPluginBase {
 
   /**
diff --git a/core/modules/migrate/src/Plugin/migrate/source/EmbeddedDataSource.php b/core/modules/migrate/src/Plugin/migrate/source/EmbeddedDataSource.php
index 251df66accba95e1dfe56afe557114275280cfe5..a61a951f3e055bd13193b6b852db1afa0a606855 100644
--- a/core/modules/migrate/src/Plugin/migrate/source/EmbeddedDataSource.php
+++ b/core/modules/migrate/src/Plugin/migrate/source/EmbeddedDataSource.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\migrate\Plugin\migrate\source;
 
-use Drupal\migrate\Attribute\MigrateSource;
 use Drupal\migrate\Plugin\MigrationInterface;
 
 /**
@@ -41,11 +40,12 @@
  *
  * For additional configuration keys, refer to the parent class:
  * @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
+ *
+ * @MigrateSource(
+ *   id = "embedded_data",
+ *   source_module = "migrate"
+ * )
  */
-#[MigrateSource(
-  id: 'embedded_data',
-  source_module: 'migrate'
-)]
 class EmbeddedDataSource extends SourcePluginBase {
 
   /**
diff --git a/core/modules/migrate/src/Plugin/migrate/source/EmptySource.php b/core/modules/migrate/src/Plugin/migrate/source/EmptySource.php
index ee56876cdc0b391e65bb27f2489dcda7d1fe8814..2991aeec7a2626f58eb45680c9e8c876216365d9 100644
--- a/core/modules/migrate/src/Plugin/migrate/source/EmptySource.php
+++ b/core/modules/migrate/src/Plugin/migrate/source/EmptySource.php
@@ -2,8 +2,6 @@
 
 namespace Drupal\migrate\Plugin\migrate\source;
 
-use Drupal\migrate\Attribute\MigrateSource;
-
 /**
  * Source returning a row based on the constants provided.
  *
@@ -23,11 +21,12 @@
  *
  * For additional configuration keys, refer to the parent class:
  * @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
+ *
+ * @MigrateSource(
+ *   id = "empty",
+ *   source_module = "migrate"
+ * )
  */
-#[MigrateSource(
-  id: 'empty',
-  source_module: 'migrate',
-)]
 class EmptySource extends SourcePluginBase {
 
   /**
diff --git a/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php b/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php
index e98d41975d036c68fee07c800c8f6493cab7fc30..e6d5d786dd7fb8f70b5090ba1fafde544c659ff4 100644
--- a/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php
+++ b/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php
@@ -105,7 +105,7 @@
  * In this example, the constant 'foo' is defined with a value of 'bar'. It is
  * later used in the process pipeline to set the value of the field baz.
  *
- * @see \Drupal\migrate\Attribute\MigrateSource
+ * @see \Drupal\migrate\Annotation\MigrateSource
  * @see \Drupal\migrate\Plugin\MigrateIdMapInterface
  * @see \Drupal\migrate\Plugin\MigratePluginManager
  * @see \Drupal\migrate\Plugin\MigrateSourceInterface
diff --git a/core/modules/migrate/src/ProcessPluginBase.php b/core/modules/migrate/src/ProcessPluginBase.php
index e7b1fcc83126d0b884f0ad00b1f422707698e058..5c6978ec335d269ee81ad59880882a8d34d6db7a 100644
--- a/core/modules/migrate/src/ProcessPluginBase.php
+++ b/core/modules/migrate/src/ProcessPluginBase.php
@@ -21,7 +21,7 @@
  * @see https://www.drupal.org/node/2129651
  * @see \Drupal\migrate\Plugin\MigratePluginManager
  * @see \Drupal\migrate\Plugin\MigrateProcessInterface
- * @see \Drupal\migrate\Attribute\MigrateProcess
+ * @see \Drupal\migrate\Annotation\MigrateProcessPlugin
  * @see \Drupal\migrate\Plugin\migrate\process\SkipOnEmpty
  * @see d7_field_formatter_settings.yml
  * @see plugin_api
diff --git a/core/modules/migrate/tests/modules/migrate_source_annotation_bc_test/migrate_source_annotation_bc_test.info.yml b/core/modules/migrate/tests/modules/migrate_source_annotation_bc_test/migrate_source_annotation_bc_test.info.yml
deleted file mode 100644
index a87b6c047ad28b21b3050b94c32eeecc9dab106e..0000000000000000000000000000000000000000
--- a/core/modules/migrate/tests/modules/migrate_source_annotation_bc_test/migrate_source_annotation_bc_test.info.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-name: 'Migrate module source annotation bc tests'
-type: module
-description: 'Support module for source plugin annotation discovery backwards compatibility tests'
-package: Testing
-version: VERSION
diff --git a/core/modules/migrate/tests/modules/migrate_source_annotation_bc_test/src/Plugin/migrate/source/MigrateSourceWithAnnotations.php b/core/modules/migrate/tests/modules/migrate_source_annotation_bc_test/src/Plugin/migrate/source/MigrateSourceWithAnnotations.php
deleted file mode 100644
index 145adcaa59a8227769db46ec81db1678539be314..0000000000000000000000000000000000000000
--- a/core/modules/migrate/tests/modules/migrate_source_annotation_bc_test/src/Plugin/migrate/source/MigrateSourceWithAnnotations.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-namespace Drupal\migrate_source_annotation_bc_test\Plugin\migrate\source;
-
-use Drupal\migrate\Plugin\migrate\source\SourcePluginBase;
-
-/**
- * A migration source plugin with annotations and a single provider.
- *
- * This plugin exists to test backwards compatibility of source plugin discovery
- * for plugin classes using annotations. This class has no providers other than
- * 'migrate_source_annotation_bc_test' and 'core'. This class and its annotation
- * should remain until annotation support is completely removed.
- *
- * @MigrateSource(
- *   id = "annotated",
- *   source_module = "migrate"
- * )
- */
-class MigrateSourceWithAnnotations extends SourcePluginBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function fields() {
-    return [];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function __toString() {
-    return 'Annotated';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getIds() {
-    return [];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function initializeIterator() {
-    return new \ArrayIterator();
-  }
-
-}
diff --git a/core/modules/migrate/tests/modules/migrate_source_annotation_bc_test/src/Plugin/migrate/source/MigrateSourceWithAnnotationsMultipleProviders.php b/core/modules/migrate/tests/modules/migrate_source_annotation_bc_test/src/Plugin/migrate/source/MigrateSourceWithAnnotationsMultipleProviders.php
deleted file mode 100644
index dabc2c3d70cc68c80f26ce0b6ab7e96ce0df7d04..0000000000000000000000000000000000000000
--- a/core/modules/migrate/tests/modules/migrate_source_annotation_bc_test/src/Plugin/migrate/source/MigrateSourceWithAnnotationsMultipleProviders.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-namespace Drupal\migrate_source_annotation_bc_test\Plugin\migrate\source;
-
-use Drupal\migrate_drupal\Plugin\migrate\source\EmptySource;
-
-/**
- * A migration source plugin with annotations and multiple providers.
- *
- * This plugin exists to test backwards compatibility of source plugin discovery
- * for plugin classes using annotations. This class has an additional provider,
- * because it extends a plugin in migrate_drupal. This class and its annotation
- * should remain until annotation support is completely removed.
- *
- * @MigrateSource(
- *   id = "annotated_multiple_providers",
- *   source_module = "migrate"
- * )
- */
-class MigrateSourceWithAnnotationsMultipleProviders extends EmptySource {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function __toString() {
-    return 'Annotated multiple providers';
-  }
-
-}
diff --git a/core/modules/migrate/tests/src/Kernel/Plugin/source/MigrateSourceAnnotationDiscoveryTest.php b/core/modules/migrate/tests/src/Kernel/Plugin/source/MigrateSourceAnnotationDiscoveryTest.php
deleted file mode 100644
index 324a797060171e6238953934bd76240c106393a8..0000000000000000000000000000000000000000
--- a/core/modules/migrate/tests/src/Kernel/Plugin/source/MigrateSourceAnnotationDiscoveryTest.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-
-namespace Drupal\Tests\migrate\Kernel\Plugin\source;
-
-use Drupal\KernelTests\KernelTestBase;
-
-/**
- * Tests discovery of source plugins with annotations.
- *
- * Migrate source plugins use a specific discovery class to accommodate multiple
- * providers. This is a backwards compatibility test that discovery for plugin
- * classes that have annotations still works even after all core plugins have
- * been converted to attributes.
- *
- * @group migrate
- */
-class MigrateSourceAnnotationDiscoveryTest extends KernelTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected static $modules = ['migrate'];
-
-  /**
-   * @covers \Drupal\migrate\Plugin\MigrateSourcePluginManager::getDefinitions
-   */
-  public function testGetDefinitions(): void {
-    // First, test attribute-only discovery.
-    $expected = ['embedded_data', 'empty'];
-    $source_plugins = $this->container->get('plugin.manager.migrate.source')->getDefinitions();
-    ksort($source_plugins);
-    $this->assertSame($expected, array_keys($source_plugins));
-
-    // Next, test discovery of both attributed and annotated plugins. The
-    // annotated plugin with multiple providers depends on migrate_drupal and
-    // should not be discovered with it uninstalled.
-    $expected = ['annotated', 'embedded_data', 'empty'];
-    $this->enableModules(['migrate_source_annotation_bc_test']);
-    $source_plugins = $this->container->get('plugin.manager.migrate.source')->getDefinitions();
-    ksort($source_plugins);
-    $this->assertSame($expected, array_keys($source_plugins));
-
-    // Install migrate_drupal and now the annotated plugin that depends on it
-    // should be discovered.
-    $expected = [
-      'annotated',
-      'annotated_multiple_providers',
-      'embedded_data',
-      'empty',
-    ];
-    $this->enableModules(['migrate_drupal']);
-    $source_plugins = $this->container->get('plugin.manager.migrate.source')->getDefinitions();
-    // Confirming here the that the source plugins that migrate and
-    // migrate_source_annotation_bc_test are discovered. There are additional
-    // plugins provided by migrate_drupal, but they do not need to be enumerated
-    // here.
-    $this->assertSame(array_diff($expected, array_keys($source_plugins)), []);
-  }
-
-}
diff --git a/core/modules/migrate_drupal/migrate_drupal.services.yml b/core/modules/migrate_drupal/migrate_drupal.services.yml
index 9e3662341b980814c50a3e7fb5713179dc8a31b2..80444d04750bfa4e85d1b16c105722b32f4506c3 100644
--- a/core/modules/migrate_drupal/migrate_drupal.services.yml
+++ b/core/modules/migrate_drupal/migrate_drupal.services.yml
@@ -6,7 +6,6 @@ services:
       - '@container.namespaces'
       - '@cache.discovery'
       - '@module_handler'
-      - '\Drupal\migrate_drupal\Attribute\MigrateField'
       - '\Drupal\migrate_drupal\Annotation\MigrateField'
   Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface: '@plugin.manager.migrate.field'
   logger.channel.migrate_drupal:
diff --git a/core/modules/migrate_drupal/src/Attribute/MigrateField.php b/core/modules/migrate_drupal/src/Attribute/MigrateField.php
deleted file mode 100644
index ffb529e98000885922b5d6ad79953aa8021a74f0..0000000000000000000000000000000000000000
--- a/core/modules/migrate_drupal/src/Attribute/MigrateField.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\migrate_drupal\Attribute;
-
-use Drupal\Component\Plugin\Attribute\Plugin;
-
-/**
- * Defines a field plugin attribute object.
- *
- * Field plugins are responsible for handling the migration of custom fields
- * (provided by Field API in Drupal 7) to Drupal 8+. They are allowed to alter
- * fieldable entity migrations when these migrations are being generated, and
- * can compute destination field types for individual fields during the actual
- * migration process.
- *
- * Plugin Namespace: Plugin\migrate\field
- *
- * For a working example, see
- * \Drupal\datetime\Plugin\migrate\field\DateField
- *
- * @see \Drupal\migrate\Plugin\MigratePluginManager
- * @see \Drupal\migrate_drupal\Plugin\MigrateFieldInterface;
- * @see \Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase
- * @see plugin_api
- *
- * @ingroup migration
- */
-#[\Attribute(\Attribute::TARGET_CLASS)]
-class MigrateField extends Plugin {
-
-  /**
-   * The plugin definition.
-   *
-   * @var array
-   */
-  protected $definition;
-
-  /**
-   * Constructs a migrate field attribute object.
-   *
-   * @param string $id
-   *   A unique identifier for the field plugin.
-   * @param int[] $core
-   *   (optional) The Drupal core version(s) this plugin applies to.
-   * @param int $weight
-   *   (optional) The weight of this plugin relative to other plugins servicing
-   *   the same field type and core version. The lowest weighted applicable
-   *   plugin will be used for each field.
-   * @param string[] $type_map
-   *   (optional) Map of D6 and D7 field types to D8+ field type plugin IDs.
-   * @param string|null $source_module
-   *   (optional) Identifies the system providing the data the field plugin will
-   *   read. The source_module is expected to be the name of a Drupal module
-   *   that must be installed in the source database.
-   * @param string|null $destination_module
-   *   (optional) Identifies the system handling the data the destination plugin
-   *   will write. The destination_module is expected to be the name of a Drupal
-   *   module on the destination site that must be installed.
-   * @param class-string|null $deriver
-   *   (optional) The deriver class.
-   */
-  public function __construct(
-    public readonly string $id,
-    public readonly array $core = [6],
-    public readonly int $weight = 0,
-    public readonly array $type_map = [],
-    public readonly ?string $source_module = NULL,
-    public readonly ?string $destination_module = NULL,
-    public readonly ?string $deriver = NULL
-  ) {}
-
-}
diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php b/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php
index cce492cfc34cd4f67875f142c8a53562d8d19514..5859ff3aa7dca44d8f428beb320479d61c29b060 100644
--- a/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php
+++ b/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php
@@ -11,7 +11,7 @@
  * Plugin manager for migrate field plugins.
  *
  * @see \Drupal\migrate_drupal\Plugin\MigrateFieldInterface
- * @see \Drupal\migrate\Attribute\MigrateField
+ * @see \Drupal\migrate\Annotation\MigrateField
  * @see plugin_api
  *
  * @ingroup migration
@@ -48,7 +48,7 @@ class MigrateFieldPluginManager extends MigratePluginManager implements MigrateF
    * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
    *   If the plugin cannot be determined, such as if the field type is invalid.
    *
-   * @see \Drupal\migrate_drupal\Attribute\MigrateField
+   * @see \Drupal\migrate_drupal\Annotation\MigrateField
    */
   public function getPluginIdFromFieldType($field_type, array $configuration = [], MigrationInterface $migration = NULL) {
     $core = static::DEFAULT_CORE_VERSION;
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/field/FieldPluginBase.php b/core/modules/migrate_drupal/src/Plugin/migrate/field/FieldPluginBase.php
index 36a25211ece9b299ef87ff33aaf33af85f44ccf9..b62ac0f994cc15d4d35e1230c10c09e9e1dbbb9b 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/field/FieldPluginBase.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/field/FieldPluginBase.php
@@ -11,7 +11,7 @@
  * The base class for all field plugins.
  *
  * @see \Drupal\migrate\Plugin\MigratePluginManager
- * @see \Drupal\migrate_drupal\Attribute\MigrateField
+ * @see \Drupal\migrate_drupal\Annotation\MigrateField
  * @see \Drupal\migrate_drupal\Plugin\MigrateFieldInterface
  * @see plugin_api
  *
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/source/ContentEntity.php b/core/modules/migrate_drupal/src/Plugin/migrate/source/ContentEntity.php
index bc7ff421ff7a1aca4b8d44e811701579c3281c2b..5d80f6160a77df322a8c9d6e7a8e04f5f3cdf226 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/source/ContentEntity.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/ContentEntity.php
@@ -9,7 +9,6 @@
 use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Drupal\migrate\Attribute\MigrateSource;
 use Drupal\migrate\EntityFieldDefinitionTrait;
 use Drupal\migrate\Plugin\migrate\source\SourcePluginBase;
 use Drupal\migrate\Plugin\MigrateSourceInterface;
@@ -62,12 +61,13 @@
  *
  * For additional configuration keys, refer to the parent class:
  * @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
-  */
-#[MigrateSource(
-  id: "content_entity",
-  source_module: "migrate_drupal",
-  deriver: ContentEntityDeriver::class,
-)]
+ *
+ * @MigrateSource(
+ *   id = "content_entity",
+ *   source_module = "migrate_drupal",
+ *   deriver = "\Drupal\migrate_drupal\Plugin\migrate\source\ContentEntityDeriver",
+ * )
+ */
 class ContentEntity extends SourcePluginBase implements ContainerFactoryPluginInterface {
   use EntityFieldDefinitionTrait;