diff --git a/composer.json b/composer.json
index 6791f35..9d01a44 100644
--- a/composer.json
+++ b/composer.json
@@ -3,8 +3,8 @@
     "description": "Adds a views plugin to filter for unreferenced entities.",
     "type": "drupal-module",
     "require" : {
-        "drupal/core": "^10.2 || ^11",
-        "drupal/entity_usage": "~2.0"
+        "drupal/entity_usage": "~2.0",
+        "drupal/core": "^10.2 || ^11 || ^12"
     },
     "keywords": [
         "Drupal",
diff --git a/entity_usage_plus.info.yml b/entity_usage_plus.info.yml
index e1a7d67..ddebae8 100644
--- a/entity_usage_plus.info.yml
+++ b/entity_usage_plus.info.yml
@@ -1,6 +1,6 @@
 name: Entity Usage Plus
 type: module
 description: Enhancements to the entity usage module.
-core_version_requirement: ^10.2 || ^11
+core_version_requirement: ^10.2 || ^11 || ^12
 dependencies:
   - entity_usage:entity_usage
diff --git a/entity_usage_plus.module b/entity_usage_plus.module
index f1a80f9..d3baa04 100644
--- a/entity_usage_plus.module
+++ b/entity_usage_plus.module
@@ -5,8 +5,9 @@
  * Customizations related entity usage.
  */
 
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\entity_usage_plus\Hook\EntityUsagePlusHooks;
 use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Url;
 
 /**
@@ -42,51 +43,15 @@ function entity_usage_plus_entity_operation_alter(array &$operations, EntityInte
  *
  * Add a filter to limit to unreferenced entities.
  */
+#[LegacyHook]
 function entity_usage_plus_views_data_alter(array &$data): void {
-  $entityTypeManager = \Drupal::entityTypeManager();
-  $entityTypes = $entityTypeManager->getDefinitions();
-
-  $validTargets = \Drupal::config('entity_usage.settings')
-    ->get('track_enabled_target_entity_types');
-  if ($validTargets) {
-    $entityTypes = array_filter($entityTypes, static fn (EntityTypeInterface $definition): bool => in_array($definition->id(), $validTargets));
-  }
-
-  $entityTypes = array_filter($entityTypes, static fn (EntityTypeInterface $entityType): bool => $entityTypeManager
-    ->hasHandler($entityType->id(), 'views_data'),
-  );
-
-  foreach ($entityTypes as $id => $definition) {
-    /** @var \Drupal\views\EntityViewsDataInterface $viewsHandler */
-    $viewsHandler = $entityTypeManager->getHandler($id, 'views_data');
-    $tableName = $viewsHandler->getViewsTableForEntityType($definition);
-
-    $data[$tableName]['entity_usage_plus_unreferenced'] = [
-      'title' => t('Limit to unreferenced entities'),
-      'filter' => [
-        'title' => t('Limit to unreferenced entities'),
-        'help' => t('Limit to entities that are not referenced in the entity usage table.'),
-        'field' => 'id',
-        'id' => 'entity_usage_plus_unreferenced',
-      ],
-    ];
-  }
-
+  \Drupal::service(EntityUsagePlusHooks::class)->viewsDataAlter($data);
 }
 
 /**
  * Implements hook_theme().
  */
+#[LegacyHook]
 function entity_usage_plus_theme($existing, $type, $theme, $path) {
-  return [
-    'entity_usage_plus_usage_table' => [
-      'base hook' => 'table',
-      'variables' => [
-        'header' => [],
-        'rows' => [],
-        'attributes' => [],
-      ],
-      'template' => 'entity-usage-plus-usage-table',
-    ],
-  ];
+  return \Drupal::service(EntityUsagePlusHooks::class)->theme($existing, $type, $theme, $path);
 }
diff --git a/entity_usage_plus.services.yml b/entity_usage_plus.services.yml
index 7d94674..b801538 100644
--- a/entity_usage_plus.services.yml
+++ b/entity_usage_plus.services.yml
@@ -4,3 +4,7 @@ services:
     arguments: ['@entity_type.manager', '@config.factory']
     tags:
       - { name: event_subscriber }
+
+  Drupal\entity_usage_plus\Hook\EntityUsagePlusHooks:
+    class: Drupal\entity_usage_plus\Hook\EntityUsagePlusHooks
+    autowire: true
diff --git a/src/Hook/EntityUsagePlusHooks.php b/src/Hook/EntityUsagePlusHooks.php
new file mode 100644
index 0000000..0548f3a
--- /dev/null
+++ b/src/Hook/EntityUsagePlusHooks.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Drupal\entity_usage_plus\Hook;
+
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+
+/**
+ * Hook implementations for entity_usage_plus.
+ */
+class EntityUsagePlusHooks {
+  use StringTranslationTrait;
+
+  /**
+   * Implements hook_views_data_alter().
+   *
+   * Add a filter to limit to unreferenced entities.
+   */
+  #[Hook('views_data_alter')]
+  public function viewsDataAlter(array &$data): void {
+    $entityTypeManager = \Drupal::entityTypeManager();
+    $entityTypes = $entityTypeManager->getDefinitions();
+    $validTargets = \Drupal::config('entity_usage.settings')->get('track_enabled_target_entity_types');
+    if ($validTargets) {
+      $entityTypes = array_filter($entityTypes, static fn(EntityTypeInterface $definition): bool => in_array($definition->id(), $validTargets));
+    }
+    $entityTypes = array_filter($entityTypes, static fn(EntityTypeInterface $entityType): bool => $entityTypeManager->hasHandler($entityType->id(), 'views_data'));
+    foreach ($entityTypes as $id => $definition) {
+      /** @var \Drupal\views\EntityViewsDataInterface $viewsHandler */
+      $viewsHandler = $entityTypeManager->getHandler($id, 'views_data');
+      $tableName = $viewsHandler->getViewsTableForEntityType($definition);
+      $data[$tableName]['entity_usage_plus_unreferenced'] = [
+        'title' => $this->t('Limit to unreferenced entities'),
+        'filter' => [
+          'title' => $this->t('Limit to unreferenced entities'),
+          'help' => $this->t('Limit to entities that are not referenced in the entity usage table.'),
+          'field' => 'id',
+          'id' => 'entity_usage_plus_unreferenced',
+        ],
+      ];
+    }
+  }
+
+  /**
+   * Implements hook_theme().
+   */
+  #[Hook('theme')]
+  public static function theme($existing, $type, $theme, $path) {
+    return [
+      'entity_usage_plus_usage_table' => [
+        'base hook' => 'table',
+        'variables' => [
+          'header' => [],
+          'rows' => [],
+          'attributes' => [],
+        ],
+        'template' => 'entity-usage-plus-usage-table',
+      ],
+    ];
+  }
+
+}
diff --git a/tests/src/Functional/EntityUsagePlusControllerTest.php b/tests/src/Functional/EntityUsagePlusControllerTest.php
index 0fa06ff..14a9127 100644
--- a/tests/src/Functional/EntityUsagePlusControllerTest.php
+++ b/tests/src/Functional/EntityUsagePlusControllerTest.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
 
 namespace Drupal\Tests\entity_usage_plus\Functional;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\Tests\BrowserTestBase;
 use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait;
 
@@ -12,6 +14,8 @@ use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait;
  *
  * @group entity_usage_plus
  */
+#[Group('entity_usage_plus')]
+#[RunTestsInSeparateProcesses]
 class EntityUsagePlusControllerTest extends BrowserTestBase {
   use EntityReferenceFieldCreationTrait;
 
