diff --git a/core/modules/book/src/Plugin/migrate/destination/Book.php b/core/modules/book/src/Plugin/migrate/destination/Book.php
index dcc5056c89af907650b90e5b02d5bb2df8531456..2f4ea33490660065bb02e2b8eab863d6d67c1865 100644
--- a/core/modules/book/src/Plugin/migrate/destination/Book.php
+++ b/core/modules/book/src/Plugin/migrate/destination/Book.php
@@ -3,15 +3,14 @@
 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;
 
 /**
- * @MigrateDestination(
- *   id = "book",
- *   provider = "book"
- * )
+ * Provides migrate destination plugin for Book content.
  */
+#[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 f6a33434d15bc057aee6650d7e43c49d0bb45699..9bfa3572e31e76774d86b4fa917e847eda5e923d 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 08b946f53f9abdc20baaaaecc9183163a959a8a0..c953a71869a9e98fae3f1e93d80b24d7edfbfb4e 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;
 
 /**
- * @MigrateDestination(
- *   id = "entity:file"
- * )
+ * Provides migrate destination plugin for File entities.
  */
+#[MigrateDestination('entity:file')]
 class EntityFile extends EntityContentBase {
 
   /**
diff --git a/core/modules/migrate/migrate.api.php b/core/modules/migrate/migrate.api.php
index 0339475ff0f79f3b9bc04870a9495a37fdbb6950..ca3ccd55db9a0f88b2431ca5ba7a064e352f9baa 100644
--- a/core/modules/migrate/migrate.api.php
+++ b/core/modules/migrate/migrate.api.php
@@ -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 are annotated with
- * \Drupal\migrate\Annotation\MigrateProcessPlugin annotation and must be in
+ * \Drupal\migrate\ProcessPluginBase. They have the
+ * \Drupal\migrate\Attribute\MigrateProcess attribute 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,12 +70,11 @@
  * @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 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.
+ * \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.
  *
  * @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 d7ef2ded4b0db0a2601a128c46174bc80ea73491..b7068cf68250a375e3f099d2969baaaba2557dc6 100644
--- a/core/modules/migrate/migrate.services.yml
+++ b/core/modules/migrate/migrate.services.yml
@@ -14,7 +14,13 @@ 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\Annotation\MigrateProcessPlugin']
+    arguments:
+      - process
+      - '@container.namespaces'
+      - '@cache.discovery'
+      - '@module_handler'
+      - 'Drupal\migrate\Attribute\MigrateProcess'
+      - '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
new file mode 100644
index 0000000000000000000000000000000000000000..606a24c2bb5517aa1918f21b88c9d476ffd430b7
--- /dev/null
+++ b/core/modules/migrate/src/Attribute/MigrateDestination.php
@@ -0,0 +1,52 @@
+<?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 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
new file mode 100644
index 0000000000000000000000000000000000000000..6adf0d7dfb1e282af968fa5e8520e42705184bc7
--- /dev/null
+++ b/core/modules/migrate/src/Attribute/MigrateProcess.php
@@ -0,0 +1,49 @@
+<?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 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/Plugin/MigrateDestinationInterface.php b/core/modules/migrate/src/Plugin/MigrateDestinationInterface.php
index d2c7fb7ee9947571214d39999fe0e1a60dff5ec7..d2dbe2f68abd78b7c671ccd5729e2e8b4957e45e 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\Annotation\MigrateDestination
+ * @see \Drupal\migrate\Attribute\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 b65515c3afedb86ec18ea8993edb92ec24eab18d..6b7514435f2920478aafce228ad96065bfd11677 100644
--- a/core/modules/migrate/src/Plugin/MigrateDestinationPluginManager.php
+++ b/core/modules/migrate/src/Plugin/MigrateDestinationPluginManager.php
@@ -5,13 +5,14 @@
 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\Annotation\MigrateDestination
+ * @see \Drupal\migrate\Attribute\MigrateDestination
  * @see plugin_api
  *
  * @ingroup migration
@@ -40,12 +41,15 @@ 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, $annotation = 'Drupal\migrate\Annotation\MigrateDestination') {
-    parent::__construct($type, $namespaces, $cache_backend, $module_handler, $annotation);
+  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);
     $this->entityTypeManager = $entity_type_manager;
   }
 
diff --git a/core/modules/migrate/src/Plugin/MigratePluginManager.php b/core/modules/migrate/src/Plugin/MigratePluginManager.php
index b3645dbdd0e41c3bbf3419dfb33bea71bdf8fc7c..9eba756ab1be31715f37f0afc6dbb50cb1b17ca7 100644
--- a/core/modules/migrate/src/Plugin/MigratePluginManager.php
+++ b/core/modules/migrate/src/Plugin/MigratePluginManager.php
@@ -2,6 +2,8 @@
 
 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;
@@ -11,10 +13,10 @@
  * Manages migrate plugins.
  *
  * @see hook_migrate_info_alter()
- * @see \Drupal\migrate\Annotation\MigrateSource
+ * @see \Drupal\migrate\Attribute\MigrateSource
  * @see \Drupal\migrate\Plugin\MigrateSourceInterface
  * @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
- * @see \Drupal\migrate\Annotation\MigrateProcessPlugin
+ * @see \Drupal\migrate\Attribute\MigrateProcess
  * @see \Drupal\migrate\Plugin\MigrateProcessInterface
  * @see \Drupal\migrate\Plugin\migrate\process\ProcessPluginBase
  * @see plugin_api
@@ -36,12 +38,20 @@ 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, $annotation = 'Drupal\Component\Annotation\PluginID') {
-    parent::__construct("Plugin/migrate/$type", $namespaces, $module_handler, NULL, $annotation);
+  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);
     $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 6b3832c89b6f28fab66ec79aa959184eff8e03d0..7d2d365d881718722568f54bcfc2e266f6e61b54 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\Annotation\MigrateProcessPlugin
+ * @see \Drupal\migrate\Attribute\MigrateProcess
  * @see plugin_api
  *
  * @ingroup migration
diff --git a/core/modules/migrate/src/Plugin/migrate/destination/DestinationBase.php b/core/modules/migrate/src/Plugin/migrate/destination/DestinationBase.php
index 4a7fc59d827049809449db427b392f576abd2834..5712613e218bdd8353ff336deed264ce12ddc22e 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\Annotation\MigrateDestination
+ * @see \Drupal\migrate\Attribute\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 80c5da68a5a1e1d6814a2c9e6071dd6c432a590f..a6b2e3339e52333ff9240ad86d60189ac413865f 100644
--- a/core/modules/migrate/src/Plugin/migrate/id_map/NullIdMap.php
+++ b/core/modules/migrate/src/Plugin/migrate/id_map/NullIdMap.php
@@ -2,6 +2,7 @@
 
 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;
@@ -12,9 +13,8 @@
  * 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 b9261d098943762007b561e63afa302b293de1ba..d66d3ce2fb2b34d291d8cb3308e9e22ad469d3d3 100644
--- a/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php
+++ b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php
@@ -2,6 +2,7 @@
 
 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;
@@ -30,9 +31,8 @@
  *
  * 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 38a58ed4a405e5ad374481707df3fdaca98a1094..c6d9024926593e6c97d5802d2d37e35cd0c12415 100644
--- a/core/modules/migrate/src/Plugin/migrate/process/Explode.php
+++ b/core/modules/migrate/src/Plugin/migrate/process/Explode.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\migrate\Plugin\migrate\process;
 
+use Drupal\migrate\Attribute\MigrateProcess;
 use Drupal\migrate\ProcessPluginBase;
 use Drupal\migrate\MigrateException;
 use Drupal\migrate\MigrateExecutableInterface;
@@ -86,11 +87,8 @@
  * 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/ProcessPluginBase.php b/core/modules/migrate/src/ProcessPluginBase.php
index 5c6978ec335d269ee81ad59880882a8d34d6db7a..e7b1fcc83126d0b884f0ad00b1f422707698e058 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\Annotation\MigrateProcessPlugin
+ * @see \Drupal\migrate\Attribute\MigrateProcess
  * @see \Drupal\migrate\Plugin\migrate\process\SkipOnEmpty
  * @see d7_field_formatter_settings.yml
  * @see plugin_api
diff --git a/core/modules/migrate_drupal/migrate_drupal.services.yml b/core/modules/migrate_drupal/migrate_drupal.services.yml
index 80444d04750bfa4e85d1b16c105722b32f4506c3..9e3662341b980814c50a3e7fb5713179dc8a31b2 100644
--- a/core/modules/migrate_drupal/migrate_drupal.services.yml
+++ b/core/modules/migrate_drupal/migrate_drupal.services.yml
@@ -6,6 +6,7 @@ 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
new file mode 100644
index 0000000000000000000000000000000000000000..ffb529e98000885922b5d6ad79953aa8021a74f0
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Attribute/MigrateField.php
@@ -0,0 +1,74 @@
+<?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 5859ff3aa7dca44d8f428beb320479d61c29b060..cce492cfc34cd4f67875f142c8a53562d8d19514 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\Annotation\MigrateField
+ * @see \Drupal\migrate\Attribute\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\Annotation\MigrateField
+   * @see \Drupal\migrate_drupal\Attribute\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 b62ac0f994cc15d4d35e1230c10c09e9e1dbbb9b..36a25211ece9b299ef87ff33aaf33af85f44ccf9 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\Annotation\MigrateField
+ * @see \Drupal\migrate_drupal\Attribute\MigrateField
  * @see \Drupal\migrate_drupal\Plugin\MigrateFieldInterface
  * @see plugin_api
  *