diff --git a/entity_reference_integrity.info.yml b/entity_reference_integrity.info.yml
index afb76b8..f93efb9 100644
--- a/entity_reference_integrity.info.yml
+++ b/entity_reference_integrity.info.yml
@@ -1,6 +1,6 @@
 name: Entity Reference Integrity
 description: Protect entities from being deleted if they are the target of an entity reference field.
-core_version_requirement: ^10.2 || ^11
+core_version_requirement: ^11.2 || ^12
 type: module
 
 package: Entity Reference Integrity
diff --git a/entity_reference_integrity.module b/entity_reference_integrity.module
index 655f379..acce942 100644
--- a/entity_reference_integrity.module
+++ b/entity_reference_integrity.module
@@ -4,17 +4,14 @@
  * @file
  * Module file.
  */
-
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\entity_reference_integrity\Hook\EntityReferenceIntegrityHooks;
 use Drupal\entity_reference_integrity\EntityReferenceIntegrityEntityHandler;
 
 /**
  * Implements hook_entity_type_alter().
  */
+#[LegacyHook]
 function entity_reference_integrity_entity_type_alter(array &$entity_types) {
-  /** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
-  foreach ($entity_types as $entity_type) {
-    if (!$entity_type->hasHandlerClass('entity_reference_integrity')) {
-      $entity_type->setHandlerClass('entity_reference_integrity', EntityReferenceIntegrityEntityHandler::class);
-    }
-  }
+  \Drupal::service(EntityReferenceIntegrityHooks::class)->entityTypeAlter($entity_types);
 }
diff --git a/entity_reference_integrity.services.yml b/entity_reference_integrity.services.yml
index 34f1af0..9c3657d 100644
--- a/entity_reference_integrity.services.yml
+++ b/entity_reference_integrity.services.yml
@@ -2,3 +2,7 @@ services:
   entity_reference_integrity.field_map:
     class: \Drupal\entity_reference_integrity\DependencyFieldMapGenerator
     arguments: ['@entity_field.manager', '@entity_type.manager', 'entity_reference', 'target_type']
+
+  Drupal\entity_reference_integrity\Hook\EntityReferenceIntegrityHooks:
+    class: Drupal\entity_reference_integrity\Hook\EntityReferenceIntegrityHooks
+    autowire: true
diff --git a/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.info.yml b/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.info.yml
index 7b46c2c..5a90253 100644
--- a/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.info.yml
+++ b/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.info.yml
@@ -1,7 +1,7 @@
 name: Entity Reference Integrity Enforce
 description: Enforce reference integrity on entities.
 package: Entity Reference Integrity
-core_version_requirement: ^10.2 || ^11
+core_version_requirement: ^11.2 || ^12
 type: module
 
 dependencies:
diff --git a/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.module b/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.module
index 80caa24..da41f58 100644
--- a/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.module
+++ b/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.module
@@ -4,7 +4,8 @@
  * @file
  * Module file.
  */
-
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\entity_reference_integrity_enforce\Hook\EntityReferenceIntegrityEnforceHooks;
 use Drupal\Core\Access\AccessResult;
 use Drupal\Core\Access\AccessResultForbidden;
 use Drupal\Core\Action\Plugin\Action\DeleteAction as CoreDeleteAction;
@@ -19,56 +20,26 @@ use Drupal\entity_reference_integrity_enforce\Plugin\Action\DeleteAction;
 /**
  * Implements hook_form_alter().
  */
+#[LegacyHook]
 function entity_reference_integrity_enforce_form_alter(&$form, FormStateInterface $form_state, $form_id) {
-  \Drupal::service('class_resolver')
-    ->getInstanceFromDefinition(FormAlter::class)
-    ->formAlter($form, $form_state, $form_id);
+  \Drupal::service(EntityReferenceIntegrityEnforceHooks::class)->formAlter($form, $form_state, $form_id);
 }
 
 /**
  * Implements hook_entity_predelete().
  */
+#[LegacyHook]
 function entity_reference_integrity_enforce_entity_predelete(EntityInterface $entity) {
-  \Drupal::service('class_resolver')
-    ->getInstanceFromDefinition(EntityPredelete::class)
-    ->entityDelete($entity);
+  \Drupal::service(EntityReferenceIntegrityEnforceHooks::class)->entityPredelete($entity);
 }
 
 /**
  * Implements hook_entity_access().
  */
-function entity_reference_integrity_enforce_entity_access(EntityInterface $entity, $operation, AccountInterface $account) {
-
-  // Only check access for delete operations.
-  if ($operation != 'delete') {
-    return AccessResult::neutral();
-  }
-
-  // Only check access for valid routes. This can return NULL.
-  $route = \Drupal::routeMatch()->getRouteObject();
-  if (empty($route)) {
-    return AccessResult::neutral();
-  }
-
-  // Only check access for API endpoints by checking the route _format.
-  // @todo Check formats for other API endpoints such as GraphQL and REST.
-  $api_formats = ['api_json'];
-  $format = $route->getRequirement('_format');
-  if (empty($format) || !in_array($format, $api_formats)) {
-    return AccessResult::neutral();
-  }
-
-  /** @var \Drupal\entity_reference_integrity\EntityReferenceIntegrityEntityHandler $entity_reference_integrity_handler */
-  $entity_reference_integrity_handler = \Drupal::entityTypeManager()->getHandler($entity->getEntityTypeId(), 'entity_reference_integrity');
-  $enabled_entity_type_ids = \Drupal::configFactory()->get('entity_reference_integrity_enforce.settings')->get('enabled_entity_type_ids');
-
-  // Finally deny access if the entity has dependents.
-  if (in_array($entity->getEntityTypeId(), $enabled_entity_type_ids, TRUE) && $entity_reference_integrity_handler->hasDependents($entity)) {
-    $reason = EntityReferenceIntegrityEntityHandler::getAccessDeniedReason($entity, FALSE);
-    return new AccessResultForbidden($reason);
-  }
-
-  return AccessResult::neutral();
+#[LegacyHook]
+function entity_reference_integrity_enforce_entity_access(EntityInterface $entity, $operation, AccountInterface $account)
+{
+    return \Drupal::service(EntityReferenceIntegrityEnforceHooks::class)->entityAccess($entity, $operation, $account);
 }
 
 /**
@@ -85,11 +56,7 @@ function entity_reference_integrity_enforce_module_implements_alter(&$implementa
 /**
  * Implements hook_action_info_alter().
  */
+#[LegacyHook]
 function entity_reference_integrity_enforce_action_info_alter(&$definitions) {
-  // Replace the core entity:delete_action plugin.
-  foreach ($definitions as &$definition) {
-    if ($definition['id'] === 'entity:delete_action' && $definition['class'] === CoreDeleteAction::class) {
-      $definition['class'] = DeleteAction::class;
-    }
-  }
+  \Drupal::service(EntityReferenceIntegrityEnforceHooks::class)->actionInfoAlter($definitions);
 }
diff --git a/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.services.yml b/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.services.yml
new file mode 100644
index 0000000..83b5575
--- /dev/null
+++ b/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.services.yml
@@ -0,0 +1,5 @@
+
+services:
+  Drupal\entity_reference_integrity_enforce\Hook\EntityReferenceIntegrityEnforceHooks:
+    class: Drupal\entity_reference_integrity_enforce\Hook\EntityReferenceIntegrityEnforceHooks
+    autowire: true
diff --git a/modules/entity_reference_integrity_enforce/src/Hook/EntityReferenceIntegrityEnforceHooks.php b/modules/entity_reference_integrity_enforce/src/Hook/EntityReferenceIntegrityEnforceHooks.php
new file mode 100644
index 0000000..67d4aaf
--- /dev/null
+++ b/modules/entity_reference_integrity_enforce/src/Hook/EntityReferenceIntegrityEnforceHooks.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace Drupal\entity_reference_integrity_enforce\Hook;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Access\AccessResultForbidden;
+use Drupal\Core\Action\Plugin\Action\DeleteAction as CoreDeleteAction;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\entity_reference_integrity\EntityReferenceIntegrityEntityHandler;
+use Drupal\entity_reference_integrity_enforce\FormAlter;
+use Drupal\entity_reference_integrity_enforce\EntityPredelete;
+use Drupal\entity_reference_integrity_enforce\Plugin\Action\DeleteAction;
+use Drupal\Core\Hook\Attribute\Hook;
+/**
+ * Hook implementations for entity_reference_integrity_enforce.
+ */
+class EntityReferenceIntegrityEnforceHooks
+{
+    /**
+     * Implements hook_form_alter().
+     */
+    #[Hook('form_alter')]
+    public static function formAlter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
+    {
+        \Drupal::service('class_resolver')->getInstanceFromDefinition(\Drupal\entity_reference_integrity_enforce\FormAlter::class)->formAlter($form, $form_state, $form_id);
+    }
+    /**
+     * Implements hook_entity_predelete().
+     */
+    #[Hook('entity_predelete')]
+    public static function entityPredelete(\Drupal\Core\Entity\EntityInterface $entity)
+    {
+        \Drupal::service('class_resolver')->getInstanceFromDefinition(\Drupal\entity_reference_integrity_enforce\EntityPredelete::class)->entityDelete($entity);
+    }
+    /**
+     * Implements hook_entity_access().
+     */
+    #[Hook('entity_access')]
+    public static function entityAccess(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account)
+    {
+        // Only check access for delete operations.
+        if ($operation != 'delete') {
+            return \Drupal\Core\Access\AccessResult::neutral();
+        }
+        // Only check access for valid routes. This can return NULL.
+        $route = \Drupal::routeMatch()->getRouteObject();
+        if (empty($route)) {
+            return \Drupal\Core\Access\AccessResult::neutral();
+        }
+        // Only check access for API endpoints by checking the route _format.
+        // @todo Check formats for other API endpoints such as GraphQL and REST.
+        $api_formats = [
+            'api_json',
+        ];
+        $format = $route->getRequirement('_format');
+        if (empty($format) || !in_array($format, $api_formats)) {
+            return \Drupal\Core\Access\AccessResult::neutral();
+        }
+        /** @var \Drupal\entity_reference_integrity\EntityReferenceIntegrityEntityHandler $entity_reference_integrity_handler */
+        $entity_reference_integrity_handler = \Drupal::entityTypeManager()->getHandler($entity->getEntityTypeId(), 'entity_reference_integrity');
+        $enabled_entity_type_ids = \Drupal::configFactory()->get('entity_reference_integrity_enforce.settings')->get('enabled_entity_type_ids');
+        // Finally deny access if the entity has dependents.
+        if (in_array($entity->getEntityTypeId(), $enabled_entity_type_ids, TRUE) && $entity_reference_integrity_handler->hasDependents($entity)) {
+            $reason = \Drupal\entity_reference_integrity\EntityReferenceIntegrityEntityHandler::getAccessDeniedReason($entity, FALSE);
+            return new \Drupal\Core\Access\AccessResultForbidden($reason);
+        }
+        return \Drupal\Core\Access\AccessResult::neutral();
+    }
+    /**
+     * Implements hook_action_info_alter().
+     */
+    #[Hook('action_info_alter')]
+    public static function actionInfoAlter(&$definitions)
+    {
+        // Replace the core entity:delete_action plugin.
+        foreach ($definitions as &$definition) {
+            if ($definition['id'] === 'entity:delete_action' && $definition['class'] === \Drupal\Core\Action\Plugin\Action\DeleteAction::class) {
+                $definition['class'] = \Drupal\entity_reference_integrity_enforce\Plugin\Action\DeleteAction::class;
+            }
+        }
+    }
+}
diff --git a/modules/entity_reference_integrity_enforce/tests/src/Functional/EnforcedIntegrityTest.php b/modules/entity_reference_integrity_enforce/tests/src/Functional/EnforcedIntegrityTest.php
index c9c5025..aece35e 100644
--- a/modules/entity_reference_integrity_enforce/tests/src/Functional/EnforcedIntegrityTest.php
+++ b/modules/entity_reference_integrity_enforce/tests/src/Functional/EnforcedIntegrityTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\entity_reference_integrity_enforce\Functional;
 
+use Drupal\Component\Utility\DeprecationHelper;
+use Drupal\entity_test\EntityTestHelper;
 use Drupal\Core\Entity\EntityStorageException;
 use Drupal\entity_reference_integrity_enforce\Exception\ProtectedEntityException;
 use Drupal\Core\Entity\EntityInterface;
@@ -128,7 +130,7 @@ class EnforcedIntegrityTest extends BrowserTestBase {
   protected function createDependentEntity(EntityInterface $entity) {
     // Create a bundle with the name name as the target entity type ID and an
     // entity reference field to link the two.
-    entity_test_create_bundle($entity->getEntityTypeId());
+    DeprecationHelper::backwardsCompatibleCall(\Drupal::VERSION, '11.2.0', fn() => EntityTestHelper::createBundle($entity->getEntityTypeId()), fn() => entity_test_create_bundle($entity->getEntityTypeId()));
     FieldStorageConfig::create([
       'field_name' => 'test_reference_field',
       'entity_type' => 'entity_test',
diff --git a/src/Hook/EntityReferenceIntegrityHooks.php b/src/Hook/EntityReferenceIntegrityHooks.php
new file mode 100644
index 0000000..d61ec81
--- /dev/null
+++ b/src/Hook/EntityReferenceIntegrityHooks.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Drupal\entity_reference_integrity\Hook;
+
+use Drupal\entity_reference_integrity\EntityReferenceIntegrityEntityHandler;
+use Drupal\Core\Hook\Attribute\Hook;
+/**
+ * Hook implementations for entity_reference_integrity.
+ */
+class EntityReferenceIntegrityHooks
+{
+    /**
+     * Implements hook_entity_type_alter().
+     */
+    #[Hook('entity_type_alter')]
+    public static function entityTypeAlter(array &$entity_types)
+    {
+        /** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
+        foreach ($entity_types as $entity_type) {
+            if (!$entity_type->hasHandlerClass('entity_reference_integrity')) {
+                $entity_type->setHandlerClass('entity_reference_integrity', \Drupal\entity_reference_integrity\EntityReferenceIntegrityEntityHandler::class);
+            }
+        }
+    }
+}
