diff --git a/modules/typed_entity_example/src/Hook/TypedEntityExampleHooks.php b/modules/typed_entity_example/src/Hook/TypedEntityExampleHooks.php
new file mode 100644
index 0000000..5aa67d7
--- /dev/null
+++ b/modules/typed_entity_example/src/Hook/TypedEntityExampleHooks.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace Drupal\typed_entity_example\Hook;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Access\AccessibleInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+
+/**
+ * Hook implementations for typed_entity_example.
+ */
+class TypedEntityExampleHooks {
+
+  /**
+   * Implements hook_entity_access().
+   *
+   * NOTE: This is for demonstrations of the APIs. If you were to implement this
+   * hook you would not want to do it this way. See the linked article for a
+   * better pattern.
+   *
+   * @see https://www.lullabot.com/articles/maintainable-code-drupal-wrapped-entities
+   */
+  #[Hook('entity_access')]
+  public function entityAccess(EntityInterface $entity, $operation, AccountInterface $account) {
+    $repository = typed_entity_repository_manager()->repositoryFromEntity($entity);
+    if (!$repository instanceof AccessibleInterface) {
+      return AccessResult::neutral();
+    }
+    $access = $repository->access($operation, $account, TRUE);
+    if (!$access->isNeutral()) {
+      return $access;
+    }
+    $wrapped = $repository->wrap($entity);
+    if (!$wrapped instanceof AccessibleInterface) {
+      return AccessResult::neutral();
+    }
+    return $wrapped->access($operation, $account, TRUE);
+  }
+
+}
diff --git a/modules/typed_entity_example/tests/src/Unit/Render/Article/FullTest.php b/modules/typed_entity_example/tests/src/Unit/Render/Article/FullTest.php
index cef1fa7..61ea4ab 100644
--- a/modules/typed_entity_example/tests/src/Unit/Render/Article/FullTest.php
+++ b/modules/typed_entity_example/tests/src/Unit/Render/Article/FullTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\typed_entity_example\Unit\Render\Article;
 
+use PHPUnit\Framework\Attributes\Group;
 use Prophecy\PhpUnit\ProphecyTrait;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Tests\UnitTestCase;
@@ -15,9 +16,11 @@ use Drupal\typed_entity_example\Render\Article\Full;
  *
  * @group typed_entity_example
  */
+#[Group('typed_entity_example')]
 class FullTest extends UnitTestCase {
 
   use ProphecyTrait;
+
   /**
    * Tests the preprocessing for articles with the full view mode.
    *
diff --git a/modules/typed_entity_example/tests/src/Unit/WrappedEntities/UserTest.php b/modules/typed_entity_example/tests/src/Unit/WrappedEntities/UserTest.php
index 690b0bc..6526282 100644
--- a/modules/typed_entity_example/tests/src/Unit/WrappedEntities/UserTest.php
+++ b/modules/typed_entity_example/tests/src/Unit/WrappedEntities/UserTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\typed_entity_example\Unit\WrappedEntities;
 
+use PHPUnit\Framework\Attributes\Group;
 use Prophecy\PhpUnit\ProphecyTrait;
 use Drupal\Core\Entity\FieldableEntityInterface;
 use Drupal\Tests\UnitTestCase;
@@ -14,9 +15,11 @@ use Drupal\typed_entity_example\WrappedEntities\User;
  *
  * @group typed_entity_example
  */
+#[Group('typed_entity_example')]
 class UserTest extends UnitTestCase {
 
   use ProphecyTrait;
+
   /**
    * Tests the nickname.
    *
diff --git a/modules/typed_entity_example/typed_entity_example.module b/modules/typed_entity_example/typed_entity_example.module
index 1c2d5ae..3d44117 100644
--- a/modules/typed_entity_example/typed_entity_example.module
+++ b/modules/typed_entity_example/typed_entity_example.module
@@ -5,8 +5,8 @@
  * Module implementation file.
  */
 
-use Drupal\Core\Access\AccessibleInterface;
-use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\typed_entity_example\Hook\TypedEntityExampleHooks;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Session\AccountInterface;
 
@@ -19,18 +19,7 @@ use Drupal\Core\Session\AccountInterface;
  *
  * @see https://www.lullabot.com/articles/maintainable-code-drupal-wrapped-entities
  */
+#[LegacyHook]
 function typed_entity_example_entity_access(EntityInterface $entity, $operation, AccountInterface $account) {
-  $repository = typed_entity_repository_manager()->repositoryFromEntity($entity);
-  if (!$repository instanceof AccessibleInterface) {
-    return AccessResult::neutral();
-  }
-  $access = $repository->access($operation, $account, TRUE);
-  if (!$access->isNeutral()) {
-    return $access;
-  }
-  $wrapped = $repository->wrap($entity);
-  if (!$wrapped instanceof AccessibleInterface) {
-    return AccessResult::neutral();
-  }
-  return $wrapped->access($operation, $account, TRUE);
+  return \Drupal::service(TypedEntityExampleHooks::class)->entityAccess($entity, $operation, $account);
 }
diff --git a/modules/typed_entity_example/typed_entity_example.services.yml b/modules/typed_entity_example/typed_entity_example.services.yml
new file mode 100644
index 0000000..673ca0f
--- /dev/null
+++ b/modules/typed_entity_example/typed_entity_example.services.yml
@@ -0,0 +1,5 @@
+
+services:
+  Drupal\typed_entity_example\Hook\TypedEntityExampleHooks:
+    class: Drupal\typed_entity_example\Hook\TypedEntityExampleHooks
+    autowire: true
diff --git a/modules/typed_entity_ui/src/Hook/TypedEntityUiHooks.php b/modules/typed_entity_ui/src/Hook/TypedEntityUiHooks.php
new file mode 100644
index 0000000..941ed2f
--- /dev/null
+++ b/modules/typed_entity_ui/src/Hook/TypedEntityUiHooks.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Drupal\typed_entity_ui\Hook;
+
+use Drupal\Core\Hook\Attribute\Hook;
+
+/**
+ * Hook implementations for typed_entity_ui.
+ */
+class TypedEntityUiHooks {
+
+  /**
+   * Implements hook_theme().
+   */
+  #[Hook('theme')]
+  public function theme(array $existing, string $type, string $theme, string $path): array {
+    return [
+      'php_class_info' => [
+        'variables' => [
+          'class_name' => NULL,
+        ],
+      ],
+      'class_with_variants' => [
+        'variables' => [
+          'object' => NULL,
+          'base_class' => NULL,
+        ],
+      ],
+      'php_class_summary' => [
+        'variables' => [
+          'class_name' => NULL,
+          'with_comment' => TRUE,
+          'with_fqn' => TRUE,
+          'with_attribute' => TRUE,
+        ],
+      ],
+    ];
+  }
+
+}
diff --git a/modules/typed_entity_ui/tests/src/Functional/ExploreDetailsTest.php b/modules/typed_entity_ui/tests/src/Functional/ExploreDetailsTest.php
index 5052f12..02be3b3 100644
--- a/modules/typed_entity_ui/tests/src/Functional/ExploreDetailsTest.php
+++ b/modules/typed_entity_ui/tests/src/Functional/ExploreDetailsTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\typed_entity_ui\Functional;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\Core\Url;
 use Drupal\node\Entity\NodeType;
 use Drupal\Tests\BrowserTestBase;
@@ -13,6 +15,8 @@ use Drupal\Tests\BrowserTestBase;
  *
  * @group typed_entity_ui
  */
+#[Group('typed_entity_ui')]
+#[RunTestsInSeparateProcesses]
 class ExploreDetailsTest extends BrowserTestBase {
 
   /**
diff --git a/modules/typed_entity_ui/typed_entity_ui.module b/modules/typed_entity_ui/typed_entity_ui.module
index 6c19e6d..4caf18b 100644
--- a/modules/typed_entity_ui/typed_entity_ui.module
+++ b/modules/typed_entity_ui/typed_entity_ui.module
@@ -5,6 +5,8 @@
  * Module implementation file.
  */
 
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\typed_entity_ui\Hook\TypedEntityUiHooks;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\typed_entity\Attribute\TypedRepository;
 use Drupal\typed_entity\ClassWithVariantsInterface;
@@ -12,28 +14,9 @@ use Drupal\typed_entity\ClassWithVariantsInterface;
 /**
  * Implements hook_theme().
  */
+#[LegacyHook]
 function typed_entity_ui_theme(array $existing, string $type, string $theme, string $path): array {
-  return [
-    'php_class_info' => [
-      'variables' => [
-        'class_name' => NULL,
-      ],
-    ],
-    'class_with_variants' => [
-      'variables' => [
-        'object' => NULL,
-        'base_class' => NULL,
-      ],
-    ],
-    'php_class_summary' => [
-      'variables' => [
-        'class_name' => NULL,
-        'with_comment' => TRUE,
-        'with_fqn' => TRUE,
-        'with_attribute' => TRUE,
-      ],
-    ],
-  ];
+  return \Drupal::service(TypedEntityUiHooks::class)->theme($existing, $type, $theme, $path);
 }
 
 /**
diff --git a/modules/typed_entity_ui/typed_entity_ui.services.yml b/modules/typed_entity_ui/typed_entity_ui.services.yml
new file mode 100644
index 0000000..2ea17c8
--- /dev/null
+++ b/modules/typed_entity_ui/typed_entity_ui.services.yml
@@ -0,0 +1,5 @@
+
+services:
+  Drupal\typed_entity_ui\Hook\TypedEntityUiHooks:
+    class: Drupal\typed_entity_ui\Hook\TypedEntityUiHooks
+    autowire: true
diff --git a/src/Hook/TypedEntityHooks.php b/src/Hook/TypedEntityHooks.php
new file mode 100644
index 0000000..55a8212
--- /dev/null
+++ b/src/Hook/TypedEntityHooks.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace Drupal\typed_entity\Hook;
+
+use Drupal\typed_entity\WrappedEntities\WrappedEntityInterface;
+use Drupal\typed_entity\Render\TypedEntityRendererInterface;
+use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+
+/**
+ * Hook implementations for typed_entity.
+ */
+class TypedEntityHooks {
+
+  /**
+   * Implements hook_entity_view_alter().
+   */
+  #[Hook('entity_view_alter')]
+  public function entityViewAlter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
+    [$renderer, $wrapped_entity] = _typed_entity_find_renderer($entity, $build);
+    if (!$renderer instanceof TypedEntityRendererInterface || !$wrapped_entity instanceof WrappedEntityInterface) {
+      return;
+    }
+    $renderer->viewAlter($build, $wrapped_entity, $display);
+  }
+
+  /**
+   * Implements hook_preprocess().
+   */
+  #[Hook('preprocess')]
+  public function preprocess(&$variables, $hook) {
+    $entity = $variables[$hook] ?? NULL;
+    if (!$entity instanceof EntityInterface) {
+      return;
+    }
+    [$renderer, $wrapped_entity] = _typed_entity_find_renderer($entity, $variables['elements'] ?? []);
+    if (!$renderer instanceof TypedEntityRendererInterface || !$wrapped_entity instanceof WrappedEntityInterface) {
+      return;
+    }
+    $renderer->preprocess($variables, $wrapped_entity);
+  }
+
+  /**
+   * Implements hook_entity_display_build_alter().
+   */
+  #[Hook('entity_display_build_alter')]
+  public function entityDisplayBuildAlter(&$build, $context) {
+    $entity = $context['entity'] ?? NULL;
+    if (!$entity instanceof EntityInterface) {
+      return;
+    }
+    [$renderer, $wrapped_entity] = _typed_entity_find_renderer($entity, $build);
+    if (!$renderer instanceof TypedEntityRendererInterface || !$wrapped_entity instanceof WrappedEntityInterface) {
+      return;
+    }
+    $renderer->displayBuildAlter($build, $wrapped_entity, $context);
+  }
+
+  /**
+   * Implements hook_entity_build_defaults_alter().
+   */
+  #[Hook('entity_build_defaults_alter')]
+  public function entityBuildDefaultsAlter(array &$build, EntityInterface $entity, $view_mode) {
+    [$renderer, $wrapped_entity] = _typed_entity_find_renderer($entity, $build);
+    if (!$renderer instanceof TypedEntityRendererInterface || !$wrapped_entity instanceof WrappedEntityInterface) {
+      return;
+    }
+    $renderer->buildDefaultsAlter($build, $wrapped_entity, $view_mode);
+  }
+
+}
diff --git a/tests/src/Kernel/EmptyFieldVariantConditionTest.php b/tests/src/Kernel/EmptyFieldVariantConditionTest.php
index 16b74a6..d8b7f15 100644
--- a/tests/src/Kernel/EmptyFieldVariantConditionTest.php
+++ b/tests/src/Kernel/EmptyFieldVariantConditionTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\typed_entity\Kernel;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\node\Entity\Node;
 use Drupal\typed_entity\TypedEntityContext;
 use Drupal\typed_entity\WrappedEntityVariants\EmptyFieldVariantCondition;
@@ -13,6 +15,8 @@ use Drupal\typed_entity\WrappedEntityVariants\EmptyFieldVariantCondition;
  *
  * @group typed_entity
  */
+#[Group('typed_entity')]
+#[RunTestsInSeparateProcesses]
 class EmptyFieldVariantConditionTest extends KernelTestBase {
 
   /**
diff --git a/tests/src/Kernel/FieldValueVariantConditionTest.php b/tests/src/Kernel/FieldValueVariantConditionTest.php
index a11c854..3756f6f 100644
--- a/tests/src/Kernel/FieldValueVariantConditionTest.php
+++ b/tests/src/Kernel/FieldValueVariantConditionTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\typed_entity\Kernel;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\node\Entity\Node;
 use Drupal\typed_entity\InvalidValueException;
 use Drupal\typed_entity\TypedEntityContext;
@@ -14,6 +16,8 @@ use Drupal\typed_entity\WrappedEntityVariants\FieldValueVariantCondition;
  *
  * @group typed_entity
  */
+#[Group('typed_entity')]
+#[RunTestsInSeparateProcesses]
 class FieldValueVariantConditionTest extends KernelTestBase {
 
   /**
diff --git a/tests/src/Kernel/RepositoryManagerTest.php b/tests/src/Kernel/RepositoryManagerTest.php
index 012de2d..c3b1a06 100644
--- a/tests/src/Kernel/RepositoryManagerTest.php
+++ b/tests/src/Kernel/RepositoryManagerTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\typed_entity\Kernel;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\node\Entity\Node;
 use Drupal\typed_entity\TypedRepositories\TypedRepositoryBase;
 use Drupal\typed_entity_test\Plugin\TypedRepositories\ArticleRepository;
@@ -14,6 +16,8 @@ use Drupal\typed_entity_test\WrappedEntities\Article;
  *
  * @group typed_entity
  */
+#[Group('typed_entity')]
+#[RunTestsInSeparateProcesses]
 class RepositoryManagerTest extends KernelTestBase {
 
   /**
diff --git a/tests/src/Kernel/TypedEntityRendererTest.php b/tests/src/Kernel/TypedEntityRendererTest.php
index 65fadf3..d2817a0 100644
--- a/tests/src/Kernel/TypedEntityRendererTest.php
+++ b/tests/src/Kernel/TypedEntityRendererTest.php
@@ -2,6 +2,9 @@
 
 namespace Drupal\Tests\typed_entity\Kernel;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
+use PHPUnit\Framework\Attributes\DataProvider;
 use Drupal\Core\Entity\FieldableEntityInterface;
 use Drupal\Core\Render\RendererInterface;
 use Drupal\typed_entity\TypedRepositories\TypedRepositoryInterface;
@@ -22,6 +25,8 @@ use Drupal\user\Entity\User;
  *
  * @group typed_entity
  */
+#[Group('typed_entity')]
+#[RunTestsInSeparateProcesses]
 class TypedEntityRendererTest extends KernelTestBase {
 
   /**
@@ -92,6 +97,7 @@ class TypedEntityRendererTest extends KernelTestBase {
    *
    * @dataProvider rendererNegotiationViewModeDataProvider
    */
+  #[DataProvider('rendererNegotiationViewModeDataProvider')]
   public function testRendererNegotiationViewMode(string $view_mode, string $expected_class): void {
     $context = new TypedEntityContext(['view_mode' => $view_mode]);
     $renderer = $this->articleRepository->rendererFactory($context);
@@ -116,6 +122,7 @@ class TypedEntityRendererTest extends KernelTestBase {
    *
    * @dataProvider rendererNegotiationStateDataProvider
    */
+  #[DataProvider('rendererNegotiationStateDataProvider')]
   public function testRendererNegotiationState(bool $state, string $expected_class): void {
     $context = new TypedEntityContext([
       'typed_entity_test.conditional_renderer' => $state,
diff --git a/tests/src/Kernel/TypedEntityRepositoryTest.php b/tests/src/Kernel/TypedEntityRepositoryTest.php
index 415bbe2..97f75fb 100644
--- a/tests/src/Kernel/TypedEntityRepositoryTest.php
+++ b/tests/src/Kernel/TypedEntityRepositoryTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\typed_entity\Kernel;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\node\Entity\Node as DrupalNode;
 use Drupal\typed_entity_test\WrappedEntities\Article;
 use Drupal\typed_entity_test\WrappedEntities\NewsArticle;
@@ -16,6 +18,8 @@ use Drupal\user\Entity\User as DrupalUser;
  *
  * @group typed_entity
  */
+#[Group('typed_entity')]
+#[RunTestsInSeparateProcesses]
 class TypedEntityRepositoryTest extends KernelTestBase {
 
   /**
diff --git a/tests/src/Kernel/WrappedEntityBaseTest.php b/tests/src/Kernel/WrappedEntityBaseTest.php
index 57807ce..ff258e9 100644
--- a/tests/src/Kernel/WrappedEntityBaseTest.php
+++ b/tests/src/Kernel/WrappedEntityBaseTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\typed_entity\Kernel;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\node\Entity\Node;
 use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait;
 use Drupal\typed_entity_test\WrappedEntities\Page;
@@ -13,6 +15,8 @@ use Drupal\typed_entity_test\WrappedEntities\Page;
  *
  * @group typed_entity
  */
+#[Group('typed_entity')]
+#[RunTestsInSeparateProcesses]
 class WrappedEntityBaseTest extends KernelTestBase {
 
   use EntityReferenceFieldCreationTrait;
diff --git a/tests/src/Unit/RepositoryManagerTest.php b/tests/src/Unit/RepositoryManagerTest.php
index d4240c9..96bc38e 100644
--- a/tests/src/Unit/RepositoryManagerTest.php
+++ b/tests/src/Unit/RepositoryManagerTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\typed_entity\Unit;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\DataProvider;
 use Prophecy\PhpUnit\ProphecyTrait;
 use Drupal\Component\Plugin\Exception\PluginNotFoundException;
 use Drupal\Core\Entity\EntityTypeManager;
@@ -19,14 +21,17 @@ use Prophecy\Argument;
  *
  * @group typed_entity
  */
+#[Group('typed_entity')]
 class RepositoryManagerTest extends UnitTestCase {
 
   use ProphecyTrait;
+
   /**
    * @covers ::get
    * @dataProvider getDataProvider
    * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
    */
+  #[DataProvider('getDataProvider')]
   public function testGet($entity_type_id, $bundle, $times): void {
     $plugin_manager = $this->prophesize(TypedRepositoryPluginManager::class);
     $plugin_ids = [
diff --git a/typed_entity.module b/typed_entity.module
index 9c0b6ff..9cfaf49 100644
--- a/typed_entity.module
+++ b/typed_entity.module
@@ -5,63 +5,43 @@
  * Module implementation file.
  */
 
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\typed_entity\Hook\TypedEntityHooks;
 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\typed_entity\TypedEntityContext;
-use Drupal\typed_entity\Render\TypedEntityRendererInterface;
 use Drupal\typed_entity\RepositoryManager;
-use Drupal\typed_entity\WrappedEntities\WrappedEntityInterface;
 
 /**
  * Implements hook_entity_view_alter().
  */
+#[LegacyHook]
 function typed_entity_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
-  [$renderer, $wrapped_entity] = _typed_entity_find_renderer($entity, $build);
-  if (!$renderer instanceof TypedEntityRendererInterface || !$wrapped_entity instanceof WrappedEntityInterface) {
-    return;
-  }
-  $renderer->viewAlter($build, $wrapped_entity, $display);
+  \Drupal::service(TypedEntityHooks::class)->entityViewAlter($build, $entity, $display);
 }
 
 /**
  * Implements hook_preprocess().
  */
+#[LegacyHook]
 function typed_entity_preprocess(&$variables, $hook) {
-  $entity = $variables[$hook] ?? NULL;
-  if (!$entity instanceof EntityInterface) {
-    return;
-  }
-  [$renderer, $wrapped_entity] = _typed_entity_find_renderer($entity, $variables['elements'] ?? []);
-  if (!$renderer instanceof TypedEntityRendererInterface || !$wrapped_entity instanceof WrappedEntityInterface) {
-    return;
-  }
-  $renderer->preprocess($variables, $wrapped_entity);
+  \Drupal::service(TypedEntityHooks::class)->preprocess($variables, $hook);
 }
 
 /**
  * Implements hook_entity_display_build_alter().
  */
+#[LegacyHook]
 function typed_entity_entity_display_build_alter(&$build, $context) {
-  $entity = $context['entity'] ?? NULL;
-  if (!$entity instanceof EntityInterface) {
-    return;
-  }
-  [$renderer, $wrapped_entity] = _typed_entity_find_renderer($entity, $build);
-  if (!$renderer instanceof TypedEntityRendererInterface || !$wrapped_entity instanceof WrappedEntityInterface) {
-    return;
-  }
-  $renderer->displayBuildAlter($build, $wrapped_entity, $context);
+  \Drupal::service(TypedEntityHooks::class)->entityDisplayBuildAlter($build, $context);
 }
 
 /**
  * Implements hook_entity_build_defaults_alter().
  */
+#[LegacyHook]
 function typed_entity_entity_build_defaults_alter(array &$build, EntityInterface $entity, $view_mode) {
-  [$renderer, $wrapped_entity] = _typed_entity_find_renderer($entity, $build);
-  if (!$renderer instanceof TypedEntityRendererInterface || !$wrapped_entity instanceof WrappedEntityInterface) {
-    return;
-  }
-  $renderer->buildDefaultsAlter($build, $wrapped_entity, $view_mode);
+  \Drupal::service(TypedEntityHooks::class)->entityBuildDefaultsAlter($build, $entity, $view_mode);
 }
 
 /**
diff --git a/typed_entity.services.yml b/typed_entity.services.yml
index 144a6c4..f458be9 100644
--- a/typed_entity.services.yml
+++ b/typed_entity.services.yml
@@ -6,3 +6,7 @@ services:
   plugin.manager.typed_entity_repository:
     class: Drupal\typed_entity\TypedRepositoryPluginManager
     parent: default_plugin_manager
+
+  Drupal\typed_entity\Hook\TypedEntityHooks:
+    class: Drupal\typed_entity\Hook\TypedEntityHooks
+    autowire: true
