Repository: avaje/avaje-inject
Pull request #567 (2024-05-14 03:25:05)

Backwards Compatible Generic Modules
Adds all the backwards compatibility stuff from #566 minus the SPI changes

rbygrave: Did you hit this issue of desiring 10.x to be backwards compatible or did someone else?  Just wondering of the pain level. Also just to say I'm kind of not loving "AvajeModule" as a name ... so I'm hoping that something better might come to me.
SentryMan: Yeah, I noticed that all the plugins and libraries I've made at work ceased to function 
SentryMan: > Need to resolve why InjectPlugin exists

The maven plugin/generator is unable to get the type array from legacy plugins.
SentryMan: > don't like "AvajeModule" as a name 

I was thinking of `AvajeModule` sort of like Guice has `GuiceModule`.

I got a couple of alternate options (just spitballing here):

- BeanModule
- ScopeModule
- GraphModule
- WiringModule
- DependencyModule
rob-bygrave: > AvajeModule sort of like Guice has GuiceModule

Yeah, that makes sense. IMO the original "Module" was a poor choice by me. "InjectModule" is taken by the annotation (which seems ok) ... so I'm definately warming to AvajeModule (it's mostly used internally).

I should get to review this again today. Great work by the way !!!

Patch:
diff --git a/blackbox-aspect/src/main/java/module-info.java b/blackbox-aspect/src/main/java/module-info.java
index 15302357..5892ce3d 100644
--- a/blackbox-aspect/src/main/java/module-info.java
+++ b/blackbox-aspect/src/main/java/module-info.java
@@ -3,6 +3,6 @@ module blackbox.aspect {
   requires io.avaje.inject;
 
   //remove this and compilation fails
-  provides io.avaje.inject.spi.Module with org.example.external.aspect.sub.ExampleExternalAspectModule;
+  provides io.avaje.inject.spi.AvajeModule with org.example.external.aspect.sub.ExampleExternalAspectModule;
 
 }
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/AvajeModule.java b/inject-generator/src/main/java/io/avaje/inject/generator/AvajeModuleData.java
similarity index 76%
rename from inject-generator/src/main/java/io/avaje/inject/generator/AvajeModule.java
rename to inject-generator/src/main/java/io/avaje/inject/generator/AvajeModuleData.java
index b77b8749..3cae4024 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/AvajeModule.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/AvajeModuleData.java
@@ -6,19 +6,19 @@ import static java.util.stream.Collectors.toList;
 import java.util.Arrays;
 import java.util.List;
 
-final class AvajeModule {
+final class AvajeModuleData {
 
   private final String fqn;
   private final List<String> provides;
   private final List<String> requires;
 
-  AvajeModule(String name, List<String> provides, List<String> requires) {
+  AvajeModuleData(String name, List<String> provides, List<String> requires) {
     this.fqn = name;
     this.provides = provides;
     this.requires = requires;
   }
 
-  AvajeModule(String[] moduleCsv) {
+  AvajeModuleData(String[] moduleCsv) {
     this.fqn = moduleCsv[0];
     this.provides = Arrays.stream(moduleCsv[1].split(",")).filter(not(String::isBlank)).collect(toList());
     this.requires = Arrays.stream(moduleCsv[2].split(",")).filter(not(String::isBlank)).collect(toList());
@@ -38,6 +38,6 @@ final class AvajeModule {
 
   @Override
   public String toString() {
-    return "AvajeModule [fqn=" + fqn + ", provides=" + provides + ", requires=" + requires + "]";
+    return "AvajeModuleData [fqn=" + fqn + ", provides=" + provides + ", requires=" + requires + "]";
   }
 }
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/Constants.java b/inject-generator/src/main/java/io/avaje/inject/generator/Constants.java
index 6c3d384d..a92ebda5 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/Constants.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/Constants.java
@@ -25,9 +25,9 @@ final class Constants {
   static final String AT_PROXY = "@Proxy";
   static final String AT_GENERATED = "@Generated(\"io.avaje.inject.generator\")";
   static final String AT_GENERATED_COMMENT = "(\"io.avaje.inject.generator\")";
-  static final String META_INF_MODULE = "META-INF/services/io.avaje.inject.spi.Module";
+  static final String META_INF_MODULE = "META-INF/services/io.avaje.inject.spi.AvajeModule";
   static final String META_INF_TESTMODULE = "META-INF/services/io.avaje.inject.test.TestModule";
-  static final String META_INF_CUSTOM = "META-INF/services/io.avaje.inject.spi.Module.Custom";
+  static final String META_INF_CUSTOM = "META-INF/services/io.avaje.inject.spi.AvajeModule.Custom";
 
   static final String BEANSCOPE = "io.avaje.inject.BeanScope";
   static final String INJECTMODULE = "io.avaje.inject.InjectModule";
@@ -52,7 +52,7 @@ final class Constants {
   static final String BEAN_FACTORY2 = "io.avaje.inject.spi.BeanFactory2";
   static final String BUILDER = "io.avaje.inject.spi.Builder";
   static final String DEPENDENCYMETA = "io.avaje.inject.spi.DependencyMeta";
-  static final String MODULE = "io.avaje.inject.spi.Module";
+  static final String MODULE = "io.avaje.inject.spi.AvajeModule";
   static final String GENERICTYPE = "io.avaje.inject.spi.GenericType";
 
   static final String CONDITIONAL_DEPENDENCY = "con:";
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/ExternalProvider.java b/inject-generator/src/main/java/io/avaje/inject/generator/ExternalProvider.java
index 2dcd677c..08a69497 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/ExternalProvider.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/ExternalProvider.java
@@ -19,6 +19,8 @@ import java.util.Set;
 
 import javax.tools.StandardLocation;
 
+import io.avaje.inject.spi.AvajeModule;
+import io.avaje.inject.spi.InjectPlugin;
 import io.avaje.inject.spi.Module;
 import io.avaje.inject.spi.Plugin;
 
@@ -29,6 +31,7 @@ import io.avaje.inject.spi.Plugin;
  */
 final class ExternalProvider {
 
+  private static final ClassLoader CLASS_LOADER = ExternalProvider.class.getClassLoader();
   private static final boolean injectAvailable = moduleCP();
   private static final Map<String, List<String>> avajePlugins = Map.ofEntries(
     entry("io.avaje.jsonb.inject.DefaultJsonbProvider", of("io.avaje.jsonb.Jsonb")),
@@ -63,14 +66,24 @@ final class ExternalProvider {
       return;
     }
 
-    final var iterator = ServiceLoader.load(Module.class, ExternalProvider.class.getClassLoader()).iterator();
-    if (!iterator.hasNext()) {
+    List<AvajeModule> modules = new ArrayList<>();
+    // load using older Module
+    ServiceLoader.load(Module.class, CLASS_LOADER).forEach(modules::add);
+    // load newer AvajeModule
+    final var iterator = ServiceLoader.load(AvajeModule.class, CLASS_LOADER).iterator();
+    while (iterator.hasNext()) {
+      try {
+        modules.add(iterator.next());
+      } catch (final ServiceConfigurationError expected) {
+        // ignore expected error reading the module that we are also writing
+      }
+    }
+    if (modules.isEmpty()) {
       APContext.logNote("No external modules detected");
       return;
     }
-    while (iterator.hasNext()) {
+    for (final var module : modules) {
       try {
-        final var module = iterator.next();
         final var name = module.getClass().getTypeName();
 
         final var provides = new ArrayList<String>();
@@ -94,7 +107,7 @@ final class ExternalProvider {
         Arrays.stream(module.requiresPackages()).map(Type::getTypeName).forEach(requires::add);
         Arrays.stream(module.autoRequiresAspects()).map(Type::getTypeName).map(Util::wrapAspect).forEach(requires::add);
 
-        ProcessingContext.addAvajeModule(new AvajeModule(name, provides, requires));
+        ProcessingContext.addAvajeModule(new AvajeModuleData(name, provides, requires));
       } catch (final ServiceConfigurationError expected) {
         // ignore expected error reading the module that we are also writing
       }
@@ -116,7 +129,12 @@ final class ExternalProvider {
     if (!injectAvailable) {
       return;
     }
-    for (final Plugin plugin : ServiceLoader.load(Plugin.class, InjectProcessor.class.getClassLoader())) {
+
+    List<InjectPlugin> plugins = new ArrayList<>();
+    ServiceLoader.load(Plugin.class, CLASS_LOADER).forEach(plugins::add);
+    ServiceLoader.load(InjectPlugin.class, CLASS_LOADER).forEach(plugins::add);
+
+    for (final var plugin : plugins) {
       var name = plugin.getClass().getTypeName();
       if (avajePlugins.containsKey(name)) {
         continue;
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/FactoryOrder.java b/inject-generator/src/main/java/io/avaje/inject/generator/FactoryOrder.java
index 827b556e..364347c9 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/FactoryOrder.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/FactoryOrder.java
@@ -13,7 +13,7 @@ import java.util.Set;
 class FactoryOrder {
 
   private final Set<String> moduleNames = new LinkedHashSet<>();
-  private final List<AvajeModule> factories = new ArrayList<>();
+  private final List<AvajeModuleData> factories = new ArrayList<>();
   private final List<FactoryState> queue = new ArrayList<>();
   private final List<FactoryState> queueNoDependencies = new ArrayList<>();
   private final Map<String, List<String>> unsatisfiedDependencies = new HashMap<>();
@@ -22,7 +22,7 @@ class FactoryOrder {
   private final Set<String> pluginProvided;
   private final List<String> loadedModules = new ArrayList<>();
 
-  FactoryOrder(Collection<AvajeModule> includeModules, Set<String> pluginProvided) {
+  FactoryOrder(Collection<AvajeModuleData> includeModules, Set<String> pluginProvided) {
     includeModules.forEach(m -> {
       add(m);
       loadedModules.add(m.name());
@@ -30,7 +30,7 @@ class FactoryOrder {
     this.pluginProvided = pluginProvided;
   }
 
-  void add(AvajeModule module) {
+  void add(AvajeModuleData module) {
     final FactoryState factoryState = new FactoryState(module);
     providesMap.computeIfAbsent(module.name(), s -> new FactoryList()).add(factoryState);
     addFactoryProvides(factoryState, module.provides());
@@ -96,7 +96,7 @@ class FactoryOrder {
     }
   }
 
-  private void unsatisfiedRequires(StringBuilder sb, AvajeModule module) {
+  private void unsatisfiedRequires(StringBuilder sb, AvajeModuleData module) {
     for (final var depModuleName : module.requires()) {
       if (notProvided(depModuleName)) {
         unsatisfiedDependencies
@@ -171,10 +171,10 @@ class FactoryOrder {
   /** Wrapper on Factory holding the pushed state. */
   static class FactoryState {
 
-    private final AvajeModule factory;
+    private final AvajeModuleData factory;
     private boolean pushed;
 
-    FactoryState(AvajeModule factory) {
+    FactoryState(AvajeModuleData factory) {
       this.factory = factory;
     }
 
@@ -187,7 +187,7 @@ class FactoryOrder {
       return pushed;
     }
 
-    AvajeModule factory() {
+    AvajeModuleData factory() {
       return factory;
     }
 
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/InjectProcessor.java b/inject-generator/src/main/java/io/avaje/inject/generator/InjectProcessor.java
index 3b1584d4..729a5030 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/InjectProcessor.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/InjectProcessor.java
@@ -95,8 +95,7 @@ public final class InjectProcessor extends AbstractProcessor {
       .filter(s -> !s.startsWith("External Module Type"))
       .distinct()
       .map(l -> l.split("\\|"))
-      .map(AvajeModule::new)
-      .peek(m -> APContext.logNote(m.toString()))
+      .map(AvajeModuleData::new)
       .forEach(ProcessingContext::addAvajeModule);
   }
 
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/ProcessingContext.java b/inject-generator/src/main/java/io/avaje/inject/generator/ProcessingContext.java
index 0693d11d..df9af117 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/ProcessingContext.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/ProcessingContext.java
@@ -28,7 +28,7 @@ final class ProcessingContext {
     private final Set<String> providedTypes = new HashSet<>();
     private final Set<String> optionalTypes = new LinkedHashSet<>();
     private final Map<String, AspectImportPrism> aspectImportPrisms = new HashMap<>();
-    private final List<AvajeModule> avajeModules = new ArrayList<>();
+    private final List<AvajeModuleData> avajeModules = new ArrayList<>();
     private final List<TypeElement> delayQueue = new ArrayList<>();
     private boolean validated;
     private boolean strictWiring;
@@ -207,11 +207,11 @@ final class ProcessingContext {
     APContext.clear();
   }
 
-  static void addAvajeModule(AvajeModule module) {
+  static void addAvajeModule(AvajeModuleData module) {
     CTX.get().avajeModules.add(module);
   }
 
-  static List<AvajeModule> avajeModules() {
+  static List<AvajeModuleData> avajeModules() {
     return CTX.get().avajeModules;
   }
 
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/ScopeInfo.java b/inject-generator/src/main/java/io/avaje/inject/generator/ScopeInfo.java
index d225c6c2..a14d6cf0 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/ScopeInfo.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/ScopeInfo.java
@@ -11,7 +11,6 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeSet;
 
 import javax.annotation.processing.FilerException;
 import javax.lang.model.element.Element;
@@ -27,11 +26,11 @@ final class ScopeInfo {
     /**
      * Default scope.
      */
-    DEFAULT("Module"),
+    DEFAULT("AvajeModule"),
     /**
      * Custom scope.
      */
-    CUSTOM("Module.Custom"),
+    CUSTOM("AvajeModule.Custom"),
     /**
      * Built-in Test scope.
      */
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/SimpleModuleWriter.java b/inject-generator/src/main/java/io/avaje/inject/generator/SimpleModuleWriter.java
index e0ca071a..ee186496 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/SimpleModuleWriter.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/SimpleModuleWriter.java
@@ -132,7 +132,7 @@ final class SimpleModuleWriter {
     provides.addAll(autoProvides);
     autoProvidesAspects.stream().map(Util::wrapAspect).forEach(provides::add);
 
-    ProcessingContext.addAvajeModule(new AvajeModule(fullName, provides, requires));
+    ProcessingContext.addAvajeModule(new AvajeModuleData(fullName, provides, requires));
   }
 
   private void writeClassesMethod() {
diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/SimpleOrderWriter.java b/inject-generator/src/main/java/io/avaje/inject/generator/SimpleOrderWriter.java
index a97b7088..80f898f1 100644
--- a/inject-generator/src/main/java/io/avaje/inject/generator/SimpleOrderWriter.java
+++ b/inject-generator/src/main/java/io/avaje/inject/generator/SimpleOrderWriter.java
@@ -62,7 +62,7 @@ final class SimpleOrderWriter {
           + "import java.util.Set;\n"
           + "import io.avaje.inject.spi.Generated;\n"
           + "import io.avaje.inject.spi.ModuleOrdering;\n"
-          + "import io.avaje.inject.spi.Module;")
+          + "import io.avaje.inject.spi.AvajeModule;")
       .eol();
 
     writer.eol();
@@ -78,7 +78,7 @@ final class SimpleOrderWriter {
     writer.append(Constants.AT_GENERATED).eol();
     writer.append("public final class %s implements ModuleOrdering {", shortName).eol().eol();
 
-    writer.append("  private final Module[] sortedModules = new Module[%s];", ordering.size()).eol();
+    writer.append("  private final AvajeModule[] sortedModules = new AvajeModule[%s];", ordering.size()).eol();
     writer.append("  private static final Map<String, Integer> INDEXES = Map.ofEntries(").eol();
     var size = ordering.size();
     var count = 0;
@@ -96,7 +96,7 @@ final class SimpleOrderWriter {
     writer.append(
       "\n"
         + "  @Override\n"
-        + "  public List<Module> factories() {\n"
+        + "  public List<AvajeModule> factories() {\n"
         + "    return List.of(sortedModules);\n"
         + "  }\n"
         + "\n"
@@ -106,7 +106,7 @@ final class SimpleOrderWriter {
         + "  }\n"
         + "\n"
         + "  @Override\n"
-        + "  public void add(Module module) {\n"
+        + "  public void add(AvajeModule module) {\n"
         + "    final var index = INDEXES.get(module.getClass().getTypeName());\n"
         + "    if (index != null) {\n"
         + "      sortedModules[index] = module;\n"
diff --git a/inject-generator/src/main/java/module-info.java b/inject-generator/src/main/java/module-info.java
index cbea9940..2b37d0d5 100644
--- a/inject-generator/src/main/java/module-info.java
+++ b/inject-generator/src/main/java/module-info.java
@@ -6,6 +6,8 @@ module io.avaje.inject.generator {
 
   uses io.avaje.inject.spi.Plugin;
   uses io.avaje.inject.spi.Module;
+  uses io.avaje.inject.spi.InjectPlugin;
+  uses io.avaje.inject.spi.AvajeModule;
 
   provides javax.annotation.processing.Processor with io.avaje.inject.generator.InjectProcessor;
 }
diff --git a/inject-maven-plugin/pom.xml b/inject-maven-plugin/pom.xml
index edf2dcbc..9f3f8a96 100644
--- a/inject-maven-plugin/pom.xml
+++ b/inject-maven-plugin/pom.xml
@@ -10,7 +10,7 @@
   <groupId>io.avaje</groupId>
   <artifactId>avaje-inject-maven-plugin</artifactId>
   <packaging>maven-plugin</packaging>
-  <version>10.0-RC2</version>
+  <version>10.0-RC3</version>
 
   <dependencies>
     <dependency>
diff --git a/inject-maven-plugin/src/main/java/io/avaje/inject/mojo/AutoProvidesMojo.java b/inject-maven-plugin/src/main/java/io/avaje/inject/mojo/AutoProvidesMojo.java
index 50e13493..757ce757 100644
--- a/inject-maven-plugin/src/main/java/io/avaje/inject/mojo/AutoProvidesMojo.java
+++ b/inject-maven-plugin/src/main/java/io/avaje/inject/mojo/AutoProvidesMojo.java
@@ -15,6 +15,7 @@ import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.ServiceLoader;
+import java.util.ServiceLoader.Provider;
 import java.util.Set;
 
 import org.apache.maven.artifact.Artifact;
@@ -28,6 +29,8 @@ import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
 
+import io.avaje.inject.spi.AvajeModule;
+import io.avaje.inject.spi.InjectPlugin;
 import io.avaje.inject.spi.Module;
 import io.avaje.inject.spi.Plugin;
 
@@ -48,7 +51,7 @@ public class AutoProvidesMojo extends AbstractMojo {
   @Parameter(defaultValue = "${project}", readonly = true, required = true)
   private MavenProject project;
 
-  private final List<AvajeModule> modules = new ArrayList<>();
+  private final List<AvajeModuleData> modules = new ArrayList<>();
 
   @Override
   public void execute() throws MojoExecutionException {
@@ -100,7 +103,16 @@ public class AutoProvidesMojo extends AbstractMojo {
     final Set<String> providedTypes = new HashSet<>();
 
     final Log log = getLog();
-    for (final var plugin : ServiceLoader.load(Plugin.class, newClassLoader)) {
+
+    final List<InjectPlugin> plugins = new ArrayList<>();
+    ServiceLoader.load(Plugin.class, newClassLoader).forEach(plugins::add);
+    ServiceLoader.load(InjectPlugin.class, newClassLoader).stream()
+        .map(Provider::get)
+        .filter(InjectPlugin.class::isInstance)
+        .map(InjectPlugin.class::cast)
+        .forEach(plugins::add);
+
+    for (final var plugin : plugins) {
       log.info("Loaded Plugin: " + plugin.getClass().getTypeName());
       for (final var provide : plugin.provides()) {
         providedTypes.add(provide.getTypeName());
@@ -120,7 +132,14 @@ public class AutoProvidesMojo extends AbstractMojo {
     final Set<String> providedTypes = new HashSet<>();
 
     final Log log = getLog();
-    for (final var module : ServiceLoader.load(Module.class, newClassLoader)) {
+    final List<AvajeModule> avajeModules = new ArrayList<>();
+    ServiceLoader.load(Module.class, newClassLoader).forEach(avajeModules::add);
+    ServiceLoader.load(AvajeModule.class, newClassLoader).stream()
+        .map(Provider::get)
+        .filter(AvajeModule.class::isInstance)
+        .map(AvajeModule.class::cast)
+        .forEach(avajeModules::add);
+    for (final var module : avajeModules) {
 
       final var name = module.getClass().getTypeName();
       log.info("Detected External Module: " + name);
@@ -142,7 +161,8 @@ public class AutoProvidesMojo extends AbstractMojo {
         provides.add(type);
       }
 
-      final var requires = Arrays.<Type>stream(module.requires()).map(Type::getTypeName).collect(toList());
+      final var requires =
+          Arrays.<Type>stream(module.requires()).map(Type::getTypeName).collect(toList());
 
       Arrays.<Type>stream(module.autoRequires()).map(Type::getTypeName).forEach(requires::add);
       Arrays.<Type>stream(module.requiresPackages()).map(Type::getTypeName).forEach(requires::add);
@@ -150,7 +170,7 @@ public class AutoProvidesMojo extends AbstractMojo {
         .map(Type::getTypeName)
         .map(AutoProvidesMojo::wrapAspect)
         .forEach(requires::add);
-      modules.add(new AvajeModule(name, provides, requires));
+      modules.add(new AvajeModuleData(name, provides, requires));
     }
 
     for (final String providedType : providedTypes) {
@@ -161,7 +181,7 @@ public class AutoProvidesMojo extends AbstractMojo {
 
   private void writeModuleCSV(FileWriter moduleWriter) throws IOException {
     moduleWriter.write("\nExternal Module Type|Provides|Requires");
-    for (AvajeModule avajeModule : modules) {
+    for (AvajeModuleData avajeModule : modules) {
       moduleWriter.write("\n");
       moduleWriter.write(avajeModule.name());
       moduleWriter.write("|");
diff --git a/inject-maven-plugin/src/main/java/io/avaje/inject/mojo/AvajeModule.java b/inject-maven-plugin/src/main/java/io/avaje/inject/mojo/AvajeModuleData.java
similarity index 81%
rename from inject-maven-plugin/src/main/java/io/avaje/inject/mojo/AvajeModule.java
rename to inject-maven-plugin/src/main/java/io/avaje/inject/mojo/AvajeModuleData.java
index dfcaa68f..c54213fc 100644
--- a/inject-maven-plugin/src/main/java/io/avaje/inject/mojo/AvajeModule.java
+++ b/inject-maven-plugin/src/main/java/io/avaje/inject/mojo/AvajeModuleData.java
@@ -3,13 +3,13 @@ package io.avaje.inject.mojo;
 import java.util.ArrayList;
 import java.util.List;
 
-final class AvajeModule {
+final class AvajeModuleData {
 
   private final String fqn;
   private final List<String> provides = new ArrayList<>();
   private final List<String> requires = new ArrayList<>();
 
-  AvajeModule(String name, List<String> provides, List<String> requires) {
+  AvajeModuleData(String name, List<String> provides, List<String> requires) {
     this.fqn = name;
     this.provides.addAll(provides);
     this.requires.addAll(requires);
diff --git a/inject/README.md b/inject/README.md
index eab0894f..0b5aeae8 100644
--- a/inject/README.md
+++ b/inject/README.md
@@ -4,13 +4,13 @@ APT based dependency injection for server side developers - https://avaje.io/inj
 ### Example module use
 
 ```java
-import io.avaje.inject.spi.Module;
+import io.avaje.inject.spi.AvajeModule;
 
 module org.example {
 
     requires io.avaje.inject;
 
-    provides io.avaje.inject.spi.Module with org.example.ExampleModule;
+    provides io.avaje.inject.spi.AvajeModule with org.example.ExampleModule;
 }
 ```
 
diff --git a/inject/src/main/java/io/avaje/inject/BeanScopeBuilder.java b/inject/src/main/java/io/avaje/inject/BeanScopeBuilder.java
index f0904434..132fcebd 100644
--- a/inject/src/main/java/io/avaje/inject/BeanScopeBuilder.java
+++ b/inject/src/main/java/io/avaje/inject/BeanScopeBuilder.java
@@ -1,6 +1,6 @@
 package io.avaje.inject;
 
-import io.avaje.inject.spi.Module;
+import io.avaje.inject.spi.AvajeModule;
 import io.avaje.inject.spi.PropertyRequiresPlugin;
 import io.avaje.lang.NonNullApi;
 import io.avaje.lang.Nullable;
@@ -77,7 +77,7 @@ public interface BeanScopeBuilder {
    * @param modules The modules that we want to include in dependency injection.
    * @return This BeanScopeBuilder
    */
-  BeanScopeBuilder modules(Module... modules);
+  BeanScopeBuilder modules(AvajeModule... modules);
 
   /**
    * Set the PropertyPlugin used for this scope. This is serviceloaded automatically of not set
diff --git a/inject/src/main/java/io/avaje/inject/DBeanScopeBuilder.java b/inject/src/main/java/io/avaje/inject/DBeanScopeBuilder.java
index 3a63e297..c4c83b5b 100644
--- a/inject/src/main/java/io/avaje/inject/DBeanScopeBuilder.java
+++ b/inject/src/main/java/io/avaje/inject/DBeanScopeBuilder.java
@@ -3,12 +3,10 @@ package io.avaje.inject;
 import static java.lang.System.Logger.Level.DEBUG;
 import static java.lang.System.Logger.Level.INFO;
 import static java.util.Collections.emptySet;
-
 import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -34,7 +32,7 @@ final class DBeanScopeBuilder implements BeanScopeBuilder.ForTesting {
   private final List<SuppliedBean> suppliedBeans = new ArrayList<>();
   @SuppressWarnings("rawtypes")
   private final List<EnrichBean> enrichBeans = new ArrayList<>();
-  private final Set<Module> includeModules = new LinkedHashSet<>();
+  private final Set<AvajeModule> includeModules = new LinkedHashSet<>();
   private final List<Runnable> postConstructList = new ArrayList<>();
   private final List<Consumer<BeanScope>> postConstructConsumerList = new ArrayList<>();
   private final List<ClosePair> preDestroyList = new ArrayList<>();
@@ -60,7 +58,7 @@ final class DBeanScopeBuilder implements BeanScopeBuilder.ForTesting {
   }
 
   @Override
-  public BeanScopeBuilder modules(Module... modules) {
+  public BeanScopeBuilder modules(AvajeModule... modules) {
     this.includeModules.addAll(Arrays.asList(modules));
     return this;
   }
@@ -254,12 +252,14 @@ final class DBeanScopeBuilder implements BeanScopeBuilder.ForTesting {
     final var start = System.currentTimeMillis();
     // load and apply plugins first
     initClassLoader();
+
+    provideDefault(ObserverManager.class, DObserverManager::new);
+
     if (propertyRequiresPlugin == null) {
       initPropertyPlugin();
     }
 
-    provideDefault(ObserverManager.class, DObserverManager::new);
-
+    ServiceLoader.load(InjectPlugin.class, classLoader).forEach(plugin -> plugin.apply(this));
     ServiceLoader.load(Plugin.class, classLoader).forEach(plugin -> plugin.apply(this));
     // sort factories by dependsOn
     ModuleOrdering factoryOrder = new FactoryOrder(parent, includeModules, !suppliedBeans.isEmpty());
@@ -267,10 +267,12 @@ final class DBeanScopeBuilder implements BeanScopeBuilder.ForTesting {
     if (factoryOrder.isEmpty()) {
       // prefer generated ModuleOrdering if provided
       factoryOrder = ServiceLoader.load(ModuleOrdering.class, classLoader).findFirst().orElse(factoryOrder);
-      ServiceLoader.load(Module.class, classLoader).forEach(factoryOrder::add);
+
+      ServiceLoader.load(AvajeModule.class).forEach(factoryOrder::add);
+      ServiceLoader.load(Module.class).forEach(factoryOrder::add);
     }
 
-    final Set<String> moduleNames = factoryOrder.orderModules();
+    final var moduleNames = factoryOrder.orderModules();
     if (moduleNames.isEmpty()) {
       throw new IllegalStateException(
         "Could not find any avaje modules."
@@ -284,7 +286,7 @@ final class DBeanScopeBuilder implements BeanScopeBuilder.ForTesting {
     log.log(level, "building with avaje modules {0} profiles {1}", moduleNames, profiles);
 
     final Builder builder = Builder.newBuilder(profiles, propertyRequiresPlugin, suppliedBeans, enrichBeans, parent, parentOverride);
-    for (final Module factory : factoryOrder.factories()) {
+    for (final var factory : factoryOrder.factories()) {
       builder.currentModule(factory.getClass());
       factory.build(builder);
     }
@@ -302,10 +304,9 @@ final class DBeanScopeBuilder implements BeanScopeBuilder.ForTesting {
     final Class<?> suppliedSuper = suppliedClass.getSuperclass();
     if (Object.class.equals(suppliedSuper)) {
       return suppliedClass;
-    } else {
-      // prefer to use the super type of the supplied bean (test double)
-      return suppliedSuper;
     }
+  // prefer to use the super type of the supplied bean (test double)
+    return suppliedSuper;
   }
 
   /** Helper to order the BeanContextFactory based on dependsOn. */
@@ -314,23 +315,23 @@ final class DBeanScopeBuilder implements BeanScopeBuilder.ForTesting {
     private final BeanScope parent;
     private final boolean suppliedBeans;
     private final Set<String> moduleNames = new LinkedHashSet<>();
-    private final List<Module> factories = new ArrayList<>();
+    private final List<AvajeModule> factories = new ArrayList<>();
     private final List<FactoryState> queue = new ArrayList<>();
     private final List<FactoryState> queueNoDependencies = new ArrayList<>();
 
     private final Map<String, FactoryList> providesMap = new HashMap<>();
 
-    FactoryOrder(BeanScope parent, Set<Module> includeModules, boolean suppliedBeans) {
+    FactoryOrder(BeanScope parent, Set<AvajeModule> includeModules, boolean suppliedBeans) {
       this.parent = parent;
       this.factories.addAll(includeModules);
       this.suppliedBeans = suppliedBeans;
-      for (final Module includeModule : includeModules) {
+      for (final AvajeModule includeModule : includeModules) {
         moduleNames.add(includeModule.getClass().getName());
       }
     }
 
     @Override
-    public void add(Module module) {
+    public void add(AvajeModule module) {
       final FactoryState factoryState = new FactoryState(module);
       providesMap
         .computeIfAbsent(module.getClass().getTypeName(), s -> new FactoryList())
@@ -379,7 +380,7 @@ final class DBeanScopeBuilder implements BeanScopeBuilder.ForTesting {
     }
 
     @Override
-    public List<Module> factories() {
+    public List<AvajeModule> factories() {
       return factories;
     }
 
@@ -436,7 +437,7 @@ final class DBeanScopeBuilder implements BeanScopeBuilder.ForTesting {
      */
     private int processQueuedFactories() {
       int count = 0;
-      final Iterator<FactoryState> it = queue.iterator();
+      final var it = queue.iterator();
       while (it.hasNext()) {
         final FactoryState factory = it.next();
         if (satisfiedDependencies(factory)) {
@@ -475,10 +476,10 @@ final class DBeanScopeBuilder implements BeanScopeBuilder.ForTesting {
   /** Wrapper on Factory holding the pushed state. */
   private static class FactoryState {
 
-    private final Module factory;
+    private final AvajeModule factory;
     private boolean pushed;
 
-    private FactoryState(Module factory) {
+    private FactoryState(AvajeModule factory) {
       this.factory = factory;
     }
 
@@ -491,7 +492,7 @@ final class DBeanScopeBuilder implements BeanScopeBuilder.ForTesting {
       return pushed;
     }
 
-    Module factory() {
+    AvajeModule factory() {
       return factory;
     }
 
diff --git a/inject/src/main/java/io/avaje/inject/spi/AvajeModule.java b/inject/src/main/java/io/avaje/inject/spi/AvajeModule.java
new file mode 100644
index 00000000..3d472af8
--- /dev/null
+++ b/inject/src/main/java/io/avaje/inject/spi/AvajeModule.java
@@ -0,0 +1,93 @@
+package io.avaje.inject.spi;
+
+import java.lang.reflect.Type;
+
+/**
+ * A AvajeModule that can be included in BeanScope.
+ */
+public interface AvajeModule {
+
+  /**
+   * Empty array of classes.
+   */
+  Class<?>[] EMPTY_CLASSES = {};
+
+  /**
+   * Return the set of types this module explicitly provides to other modules.
+   */
+  default Type[] provides() {
+    return EMPTY_CLASSES;
+  }
+
+  /**
+   * Return the types this module needs to be provided externally or via other modules.
+   */
+  default Type[] requires() {
+    return EMPTY_CLASSES;
+  }
+
+  /**
+   * Return the packages this module needs to be provided via other modules.
+   */
+  default Type[] requiresPackages() {
+    return EMPTY_CLASSES;
+  }
+
+  /**
+   * Return the classes that this module provides that we allow other modules to auto depend on.
+   *
+   * <p>This is a convenience when using multiple modules that is otherwise controlled manually by
+   * explicitly using {@link AvajeModule#provides()}.
+   */
+  default Type[] autoProvides() {
+    return EMPTY_CLASSES;
+  }
+
+  /**
+   * Return the aspects that this module provides.
+   *
+   * <p>This is a convenience when using multiple modules that we otherwise manually specify via
+   * {@link AvajeModule#provides()}.
+   */
+  default Class<?>[] autoProvidesAspects() {
+    return EMPTY_CLASSES;
+  }
+
+  /**
+   * These are the classes that this module requires for wiring that are provided by other external
+   * modules (that are in the classpath at compile time).
+   *
+   * <p>This is a convenience when using multiple modules that is otherwise controlled manually by
+   * explicitly using {@link AvajeModule#requires()} or {@link AvajeModule#requiresPackages()}.
+   */
+  default Type[] autoRequires() {
+    return EMPTY_CLASSES;
+  }
+
+  /**
+   * These are the aspects that this module requires whose implementations are provided by other
+   * external modules (that are in the classpath at compile time).
+   */
+  default Class<?>[] autoRequiresAspects() {
+    return EMPTY_CLASSES;
+  }
+
+  /**
+   * Return public classes of the beans that would be registered by this module.
+   *
+   * <p>This method allows code to use reflection to inspect the modules classes before the module
+   * is wired. This method is not required for DI wiring.
+   */
+  Class<?>[] classes();
+
+  /**
+   * Build all the beans.
+   */
+  void build(Builder builder);
+
+  /**
+   * Marker for custom scoped modules.
+   */
+  interface Custom extends AvajeModule {
+  }
+}
diff --git a/inject/src/main/java/io/avaje/inject/spi/Builder.java b/inject/src/main/java/io/avaje/inject/spi/Builder.java
index a887ac5f..5fad9539 100644
--- a/inject/src/main/java/io/avaje/inject/spi/Builder.java
+++ b/inject/src/main/java/io/avaje/inject/spi/Builder.java
@@ -284,5 +284,5 @@ public interface Builder {
   /**
    * Set the current module being wired.
    */
-  void currentModule(Class<? extends Module> currentModule);
+  void currentModule(Class<? extends AvajeModule> currentModule);
 }
diff --git a/inject/src/main/java/io/avaje/inject/spi/DBeanMap.java b/inject/src/main/java/io/avaje/inject/spi/DBeanMap.java
index 49d83ddb..f62b71e9 100644
--- a/inject/src/main/java/io/avaje/inject/spi/DBeanMap.java
+++ b/inject/src/main/java/io/avaje/inject/spi/DBeanMap.java
@@ -24,12 +24,12 @@ final class DBeanMap {
   private final Set<String> qualifiers = new HashSet<>();
 
   private NextBean nextBean;
-  private Class<? extends Module> currentModule;
+  private Class<? extends AvajeModule> currentModule;
 
   DBeanMap() {
   }
 
-  void currentModule(Class<? extends Module> currentModule) {
+  void currentModule(Class<? extends AvajeModule> currentModule) {
     this.currentModule = currentModule;
   }
 
diff --git a/inject/src/main/java/io/avaje/inject/spi/DBuilder.java b/inject/src/main/java/io/avaje/inject/spi/DBuilder.java
index 97c59ba7..40d22acc 100644
--- a/inject/src/main/java/io/avaje/inject/spi/DBuilder.java
+++ b/inject/src/main/java/io/avaje/inject/spi/DBuilder.java
@@ -46,7 +46,7 @@ class DBuilder implements Builder {
   }
 
   @Override
-  public void currentModule(Class<? extends Module> currentModule) {
+  public void currentModule(Class<? extends AvajeModule> currentModule) {
     beanMap.currentModule(currentModule);
   }
 
diff --git a/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java b/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java
index 9febe9d0..0aae58e9 100644
--- a/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java
+++ b/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java
@@ -29,7 +29,7 @@ final class DContextEntry {
     entries.add(entryBean);
   }
 
-  Provider<?> provider(String name, Class<? extends Module> currentModule) {
+  Provider<?> provider(String name, Class<? extends AvajeModule> currentModule) {
     if (entries.size() == 1) {
       return entries.get(0).provider();
     }
@@ -46,7 +46,7 @@ final class DContextEntry {
     return new EntryMatcher(name, null).match(entries);
   }
 
-  Object get(String name, Class<? extends Module> currentModule) {
+  Object get(String name, Class<? extends AvajeModule> currentModule) {
     if (entries.size() == 1) {
       return entries.get(0).bean();
     }
@@ -96,11 +96,11 @@ final class DContextEntry {
 
     private final String name;
     private final boolean impliedName;
-    private final Class<? extends Module> currentModule;
+    private final Class<? extends AvajeModule> currentModule;
     private DContextEntryBean match;
     private DContextEntryBean ignoredSecondaryMatch;
 
-    EntryMatcher(String name, Class<? extends Module> currentModule) {
+    EntryMatcher(String name, Class<? extends AvajeModule> currentModule) {
       this.currentModule = currentModule;
       if (name != null && name.startsWith("!")) {
         this.name = name.substring(1);
diff --git a/inject/src/main/java/io/avaje/inject/spi/DContextEntryBean.java b/inject/src/main/java/io/avaje/inject/spi/DContextEntryBean.java
index 41fd5059..3aaf1e26 100644
--- a/inject/src/main/java/io/avaje/inject/spi/DContextEntryBean.java
+++ b/inject/src/main/java/io/avaje/inject/spi/DContextEntryBean.java
@@ -13,7 +13,7 @@ class DContextEntryBean {
   /**
    * Create taking into account if it is a Provider or the bean itself.
    */
-  static DContextEntryBean of(Object source, String name, int flag, Class<? extends Module> currentModule) {
+  static DContextEntryBean of(Object source, String name, int flag, Class<? extends AvajeModule> currentModule) {
     if (source instanceof Provider) {
       return new ProtoProvider((Provider<?>)source, name, flag, currentModule);
     } else {
@@ -32,16 +32,16 @@ class DContextEntryBean {
     }
   }
 
-  static DContextEntryBean provider(boolean prototype, Provider<?> provider, String name, int flag, Class<? extends Module> currentModule) {
+  static DContextEntryBean provider(boolean prototype, Provider<?> provider, String name, int flag, Class<? extends AvajeModule> currentModule) {
     return prototype ? new ProtoProvider(provider, name, flag, currentModule) : new OnceProvider(provider, name, flag, currentModule);
   }
 
   protected final Object source;
   protected final String name;
-  protected final Class<? extends Module> sourceModule;
+  protected final Class<? extends AvajeModule> sourceModule;
   private final int flag;
 
-  private DContextEntryBean(Object source, String name, int flag, Class<? extends Module> currentModule) {
+  private DContextEntryBean(Object source, String name, int flag, Class<? extends AvajeModule> currentModule) {
     this.source = source;
     this.name = name;
     this.flag = flag;
@@ -76,7 +76,7 @@ class DContextEntryBean {
     return qualifierName == null ? name == null : qualifierName.equalsIgnoreCase(name);
   }
 
-  final Class<? extends Module> sourceModule() {
+  final Class<? extends AvajeModule> sourceModule() {
     return sourceModule;
   }
 
@@ -122,7 +122,7 @@ class DContextEntryBean {
 
     private final Provider<?> provider;
 
-    private ProtoProvider(Provider<?> provider, String name, int flag, Class<? extends Module> currentModule) {
+    private ProtoProvider(Provider<?> provider, String name, int flag, Class<? extends AvajeModule> currentModule) {
       super(provider, name, flag, currentModule);
       this.provider = provider;
     }
@@ -147,7 +147,7 @@ class DContextEntryBean {
     private final Provider<?> provider;
     private Object bean;
 
-    private OnceProvider(Provider<?> provider, String name, int flag, Class<? extends Module> currentModule) {
+    private OnceProvider(Provider<?> provider, String name, int flag, Class<? extends AvajeModule> currentModule) {
       super(provider, name, flag, currentModule);
       this.provider = provider;
     }
diff --git a/inject/src/main/java/io/avaje/inject/spi/InjectPlugin.java b/inject/src/main/java/io/avaje/inject/spi/InjectPlugin.java
new file mode 100644
index 00000000..89b49ed0
--- /dev/null
+++ b/inject/src/main/java/io/avaje/inject/spi/InjectPlugin.java
@@ -0,0 +1,38 @@
+package io.avaje.inject.spi;
+
+import io.avaje.inject.BeanScopeBuilder;
+
+import java.lang.reflect.Type;
+
+/**
+ * A Plugin that can be applied when creating a bean scope.
+ *
+ * <p>Typically, a plugin might provide a default dependency via {@link
+ * BeanScopeBuilder#provideDefault(Type, java.util.function.Supplier)}.
+ */
+public interface InjectPlugin {
+
+  /**
+   * Empty array of classes.
+   */
+  Class<?>[] EMPTY_CLASSES = {};
+
+  /**
+   * Apply the plugin to the scope builder.
+   */
+  void apply(BeanScopeBuilder builder);
+
+  /**
+   * Return the classes that the plugin provides.
+   */
+  default Type[] provides() {
+    return EMPTY_CLASSES;
+  }
+
+  /**
+   * Return the aspect classes that the plugin provides.
+   */
+  default Class<?>[] providesAspects() {
+    return EMPTY_CLASSES;
+  }
+}
diff --git a/inject/src/main/java/io/avaje/inject/spi/Module.java b/inject/src/main/java/io/avaje/inject/spi/Module.java
index bbfc4321..62dde5ec 100644
--- a/inject/src/main/java/io/avaje/inject/spi/Module.java
+++ b/inject/src/main/java/io/avaje/inject/spi/Module.java
@@ -6,17 +6,16 @@ import io.avaje.inject.InjectModule;
 
 /**
  * A Module that can be included in BeanScope.
+ *
+ * @deprecated migrate to {@link AvajeModule}
  */
-public interface Module {
-
-  /**
-   * Empty array of classes.
-   */
-  Class<?>[] EMPTY_CLASSES = {};
+@Deprecated(forRemoval = true)
+public interface Module extends AvajeModule {
 
   /**
    * Return the set of types this module explicitly provides to other modules.
    */
+  @Override
   default Type[] provides() {
     return EMPTY_CLASSES;
   }
@@ -24,6 +23,7 @@ public interface Module {
   /**
    * Return the types this module needs to be provided externally or via other modules.
    */
+  @Override
   default Type[] requires() {
     return EMPTY_CLASSES;
   }
@@ -31,6 +31,7 @@ public interface Module {
   /**
    * Return the packages this module needs to be provided via other modules.
    */
+  @Override
   default Type[] requiresPackages() {
     return EMPTY_CLASSES;
   }
@@ -41,6 +42,7 @@ public interface Module {
    * This is a convenience when using multiple modules that is otherwise controlled manually by
    * explicitly using {@link InjectModule#provides()}.
    */
+  @Override
   default Type[] autoProvides() {
     return EMPTY_CLASSES;
   }
@@ -51,6 +53,7 @@ public interface Module {
    * This is a convenience when using multiple modules that we otherwise manually specify via
    * {@link InjectModule#provides()}.
    */
+  @Override
   default Class<?>[] autoProvidesAspects() {
     return EMPTY_CLASSES;
   }
@@ -62,6 +65,7 @@ public interface Module {
    * This is a convenience when using multiple modules that is otherwise controlled manually by
    * explicitly using {@link InjectModule#requires()} or {@link InjectModule#requiresPackages()}.
    */
+  @Override
   default Type[] autoRequires() {
     return EMPTY_CLASSES;
   }
@@ -70,6 +74,7 @@ public interface Module {
    * These are the apects that this module requires whose implementations are provided by other external
    * modules (that are in the classpath at compile time).
    */
+  @Override
   default Class<?>[] autoRequiresAspects() {
     return EMPTY_CLASSES;
   }
@@ -80,11 +85,13 @@ public interface Module {
    * This method allows code to use reflection to inspect the modules classes
    * before the module is wired. This method is not required for DI wiring.
    */
+  @Override
   Class<?>[] classes();
 
   /**
    * Build all the beans.
    */
+  @Override
   void build(Builder builder);
 
   /**
diff --git a/inject/src/main/java/io/avaje/inject/spi/ModuleOrdering.java b/inject/src/main/java/io/avaje/inject/spi/ModuleOrdering.java
index f2300b09..6062c138 100644
--- a/inject/src/main/java/io/avaje/inject/spi/ModuleOrdering.java
+++ b/inject/src/main/java/io/avaje/inject/spi/ModuleOrdering.java
@@ -16,7 +16,7 @@ public interface ModuleOrdering {
   /**
    * The list of factories in the order they should be built.
    */
-  List<Module> factories();
+  List<AvajeModule> factories();
 
   /**
    * Whether no modules are available
@@ -26,5 +26,5 @@ public interface ModuleOrdering {
   /**
    * Accept a module for ordering
    */
-  void add(Module module);
+  void add(AvajeModule module);
 }
diff --git a/inject/src/main/java/io/avaje/inject/spi/Plugin.java b/inject/src/main/java/io/avaje/inject/spi/Plugin.java
index bb7469be..313be4ee 100644
--- a/inject/src/main/java/io/avaje/inject/spi/Plugin.java
+++ b/inject/src/main/java/io/avaje/inject/spi/Plugin.java
@@ -9,29 +9,30 @@ import java.lang.reflect.Type;
  *
  * <p>Typically, a plugin might provide a default dependency via {@link
  * BeanScopeBuilder#provideDefault(Type, java.util.function.Supplier)}.
+ *
+ * @deprecated migrate to {@link InjectPlugin}
  */
-public interface Plugin {
-
-  /**
-   * Empty array of classes.
-   */
-  Class<?>[] EMPTY_CLASSES = {};
+@Deprecated(forRemoval = true)
+public interface Plugin extends InjectPlugin {
 
   /**
    * Apply the plugin to the scope builder.
    */
+  @Override
   void apply(BeanScopeBuilder builder);
 
   /**
    * Return the classes that the plugin provides.
    */
-  default Type[] provides() {
+  @Override
+  default Class<?>[] provides() {
     return EMPTY_CLASSES;
   }
 
   /**
    * Return the aspect classes that the plugin provides.
    */
+  @Override
   default Class<?>[] providesAspects() {
     return EMPTY_CLASSES;
   }
diff --git a/inject/src/main/java/module-info.java b/inject/src/main/java/module-info.java
index aba38b6d..2bf95f0f 100644
--- a/inject/src/main/java/module-info.java
+++ b/inject/src/main/java/module-info.java
@@ -11,8 +11,10 @@ module io.avaje.inject {
   requires static io.avaje.config;
   requires static org.mockito;
 
+  uses io.avaje.inject.spi.AvajeModule;
   uses io.avaje.inject.spi.Module;
   uses io.avaje.inject.spi.ModuleOrdering;
+  uses io.avaje.inject.spi.InjectPlugin;
   uses io.avaje.inject.spi.Plugin;
   uses io.avaje.inject.spi.PropertyRequiresPlugin;
 


Test patch:
diff --git a/blackbox-test-inject/pom.xml b/blackbox-test-inject/pom.xml
index 5878b52b..81818ed2 100644
--- a/blackbox-test-inject/pom.xml
+++ b/blackbox-test-inject/pom.xml
@@ -90,7 +90,7 @@
 			<plugin>
 				<groupId>io.avaje</groupId>
 				<artifactId>avaje-inject-maven-plugin</artifactId>
-				<version>10.0-RC2</version>
+				<version>10.0-RC3</version>
 				<executions>
 					<execution>
 						<phase>process-sources</phase>
diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/InjectProcessorTest.java b/inject-generator/src/test/java/io/avaje/inject/generator/InjectProcessorTest.java
index 5d62511b..8c000a9b 100644
--- a/inject-generator/src/test/java/io/avaje/inject/generator/InjectProcessorTest.java
+++ b/inject-generator/src/test/java/io/avaje/inject/generator/InjectProcessorTest.java
@@ -37,7 +37,7 @@ class InjectProcessorTest {
           .sorted(Comparator.reverseOrder())
           .map(Path::toFile)
           .forEach(File::delete);
-      Paths.get("io.avaje.inject.spi.Module").toAbsolutePath().toFile().delete();
+      Paths.get("io.avaje.inject.spi.AvajeModule").toAbsolutePath().toFile().delete();
       Paths.get("io.avaje.inject.spi.ModuleOrdering").toAbsolutePath().toFile().delete();
     } catch (final Exception e) {
     }
diff --git a/inject-test/src/main/java/io/avaje/inject/test/GlobalInitialise.java b/inject-test/src/main/java/io/avaje/inject/test/GlobalInitialise.java
index ed949af8..457ff387 100644
--- a/inject-test/src/main/java/io/avaje/inject/test/GlobalInitialise.java
+++ b/inject-test/src/main/java/io/avaje/inject/test/GlobalInitialise.java
@@ -1,7 +1,7 @@
 package io.avaje.inject.test;
 
 import io.avaje.inject.BeanScope;
-import io.avaje.inject.spi.Module;
+import io.avaje.inject.spi.AvajeModule;
 import io.avaje.lang.Nullable;
 
 import java.io.IOException;
@@ -81,7 +81,7 @@ final class GlobalInitialise {
 
   private BeanScope buildFromModules(List<TestModule> testModules) {
     return BeanScope.builder()
-      .modules(testModules.toArray(Module[]::new))
+      .modules(testModules.toArray(AvajeModule[]::new))
       .shutdownHook(shutdownHook)
       .build();
   }
diff --git a/inject-test/src/main/java/io/avaje/inject/test/TestModule.java b/inject-test/src/main/java/io/avaje/inject/test/TestModule.java
index 4552fa18..5c646f33 100644
--- a/inject-test/src/main/java/io/avaje/inject/test/TestModule.java
+++ b/inject-test/src/main/java/io/avaje/inject/test/TestModule.java
@@ -1,9 +1,9 @@
 package io.avaje.inject.test;
 
-import io.avaje.inject.spi.Module;
+import io.avaje.inject.spi.AvajeModule;
 
 /**
  * Marker for Test scope module.
  */
-public interface TestModule extends Module.Custom {
+public interface TestModule extends AvajeModule.Custom {
 }
diff --git a/inject-test/src/test/java/org/example/coffee/BeanScopeBuilderAddTest.java b/inject-test/src/test/java/org/example/coffee/BeanScopeBuilderAddTest.java
index 91dd0e47..4a8a7837 100644
--- a/inject-test/src/test/java/org/example/coffee/BeanScopeBuilderAddTest.java
+++ b/inject-test/src/test/java/org/example/coffee/BeanScopeBuilderAddTest.java
@@ -2,7 +2,7 @@ package org.example.coffee;
 
 import io.avaje.inject.BeanScope;
 import io.avaje.inject.spi.Builder;
-import io.avaje.inject.spi.Module;
+import io.avaje.inject.spi.AvajeModule;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
@@ -28,7 +28,7 @@ public class BeanScopeBuilderAddTest {
     }
   }
 
-  public static class SillyModule implements Module {
+  public static class SillyModule implements AvajeModule {
 
     @Override
     public Class<?>[] requires() {
diff --git a/inject-test/src/test/java/org/example/custom2/ParentScopeSpyTest.java b/inject-test/src/test/java/org/example/custom2/ParentScopeSpyTest.java
index 161ecf5e..ccd685cb 100644
--- a/inject-test/src/test/java/org/example/custom2/ParentScopeSpyTest.java
+++ b/inject-test/src/test/java/org/example/custom2/ParentScopeSpyTest.java
@@ -2,7 +2,7 @@ package org.example.custom2;
 
 import io.avaje.inject.BeanScope;
 import io.avaje.inject.spi.Builder;
-import io.avaje.inject.spi.Module;
+import io.avaje.inject.spi.AvajeModule;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
@@ -64,7 +64,7 @@ class ParentScopeSpyTest {
     }
   }
 
-  static class MyTestModule implements Module.Custom {
+  static class MyTestModule implements AvajeModule.Custom {
 
     private final Class<?>[] provides = new Class<?>[]{};
     private final Class<?>[] requires = new Class<?>[]{};
diff --git a/inject/src/test/java/io/avaje/inject/BeanScopeBuilderTest.java b/inject/src/test/java/io/avaje/inject/BeanScopeBuilderTest.java
index a3a0f211..52b6d504 100644
--- a/inject/src/test/java/io/avaje/inject/BeanScopeBuilderTest.java
+++ b/inject/src/test/java/io/avaje/inject/BeanScopeBuilderTest.java
@@ -1,6 +1,6 @@
 package io.avaje.inject;
 
-import static io.avaje.inject.spi.Module.EMPTY_CLASSES;
+import static io.avaje.inject.spi.AvajeModule.EMPTY_CLASSES;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
@@ -14,9 +14,9 @@ import java.util.stream.Collectors;
 
 import org.junit.jupiter.api.Test;
 
+import io.avaje.inject.spi.AvajeModule;
 import io.avaje.inject.spi.Builder;
 import io.avaje.inject.spi.GenericType;
-import io.avaje.inject.spi.Module;
 
 @SuppressWarnings("all")
 class BeanScopeBuilderTest {
@@ -179,9 +179,9 @@ class BeanScopeBuilderTest {
       .hasMessageContaining("has unsatisfied requires [io.avaje.inject.BeanScopeBuilderTest$Mod3] ");
   }
 
-  private List<String> names(List<Module> factories) {
+  private List<String> names(List<AvajeModule> factories) {
     return factories.stream()
-      .map(Module::toString)
+      .map(AvajeModule::toString)
       .collect(Collectors.toList());
   }
 
@@ -193,7 +193,7 @@ class BeanScopeBuilderTest {
     return new TDModule(name, provides, requires, requiresPkg);
   }
 
-  private static class TDModule implements Module {
+  private static class TDModule implements AvajeModule {
 
     final String name;
     final Type[] provides;
diff --git a/inject/src/test/java/io/avaje/inject/LegacyBeanScopeBuilderTest.java b/inject/src/test/java/io/avaje/inject/LegacyBeanScopeBuilderTest.java
new file mode 100644
index 00000000..a245bb04
--- /dev/null
+++ b/inject/src/test/java/io/avaje/inject/LegacyBeanScopeBuilderTest.java
@@ -0,0 +1,338 @@
+package io.avaje.inject;
+
+import static io.avaje.inject.spi.AvajeModule.EMPTY_CLASSES;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.Test;
+
+import io.avaje.inject.spi.AvajeModule;
+import io.avaje.inject.spi.Builder;
+import io.avaje.inject.spi.Module;
+
+@SuppressWarnings("all")
+class LegacyBeanScopeBuilderTest {
+
+  @Test
+  void depends_providedByParent() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(
+            new TDBeanScope(MyFeature.class), Collections.emptySet(), false);
+    factoryOrder.add(bc("1", EMPTY_CLASSES, of(MyFeature.class)));
+    factoryOrder.orderModules();
+
+    assertThat(names(factoryOrder.factories())).containsExactly("1");
+  }
+
+  @Test
+  void depends_notProvidedByParent_expect_IllegalStateException() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(
+            new TDBeanScope(FeatureA.class), Collections.emptySet(), false);
+    factoryOrder.add(bc("1", EMPTY_CLASSES, of(MyFeature.class)));
+    assertThatThrownBy(factoryOrder::orderModules)
+        .isInstanceOf(IllegalStateException.class)
+        .hasMessageContaining(
+            "Module [io.avaje.inject.LegacyBeanScopeBuilderTest$TDModule] has unsatisfied requires [io.avaje.inject.LegacyBeanScopeBuilderTest$MyFeature]");
+  }
+
+  @Test
+  void noDepends() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(null, Collections.emptySet(), true);
+    factoryOrder.add(bc("1", EMPTY_CLASSES, EMPTY_CLASSES));
+    factoryOrder.add(bc("2", EMPTY_CLASSES, EMPTY_CLASSES));
+    factoryOrder.add(bc("3", EMPTY_CLASSES, EMPTY_CLASSES));
+    factoryOrder.orderModules();
+
+    assertThat(names(factoryOrder.factories())).containsExactly("1", "2", "3");
+  }
+
+  @Test
+  void providedFirst() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(null, Collections.emptySet(), true);
+    factoryOrder.add(bc("two", EMPTY_CLASSES, EMPTY_CLASSES));
+    factoryOrder.add(bc("one", of(Mod3.class), EMPTY_CLASSES));
+    factoryOrder.orderModules();
+
+    assertThat(names(factoryOrder.factories())).containsExactly("one", "two");
+  }
+
+  @Test
+  void name_depends() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(null, Collections.emptySet(), true);
+    factoryOrder.add(bc("two", EMPTY_CLASSES, of(Mod3.class)));
+    factoryOrder.add(bc("one", EMPTY_CLASSES, EMPTY_CLASSES));
+    factoryOrder.orderModules();
+
+    assertThat(names(factoryOrder.factories())).containsExactly("one", "two");
+  }
+
+  @Test
+  void name_depends4() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(null, Collections.emptySet(), true);
+    factoryOrder.add(bc("1", EMPTY_CLASSES, of(Mod3.class)));
+    factoryOrder.add(bc("2", EMPTY_CLASSES, of(Mod4.class)));
+    factoryOrder.add(bc("3", of(Mod3.class), of(Mod4.class)));
+    factoryOrder.add(bc("4", of(Mod4.class), null));
+
+    factoryOrder.orderModules();
+
+    assertThat(names(factoryOrder.factories())).containsExactly("4", "2", "3", "1");
+  }
+
+  @Test
+  void nameFeature_depends() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(null, Collections.emptySet(), true);
+    factoryOrder.add(bc("1", of(FeatureA.class), of(Mod3.class)));
+    factoryOrder.add(bc("2", EMPTY_CLASSES, of(Mod4.class, FeatureA.class)));
+    factoryOrder.add(bc("3", of(Mod3.class), of(Mod4.class)));
+    factoryOrder.add(bc("4", of(Mod4.class), null));
+
+    factoryOrder.orderModules();
+
+    assertThat(names(factoryOrder.factories())).containsExactly("4", "3", "1", "2");
+  }
+
+  @Test
+  void feature_depends() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(null, Collections.emptySet(), true);
+    factoryOrder.add(bc("two", EMPTY_CLASSES, of(MyFeature.class)));
+    factoryOrder.add(bc("one", of(MyFeature.class), null));
+    factoryOrder.orderModules();
+
+    assertThat(names(factoryOrder.factories())).containsExactly("one", "two");
+  }
+
+  @Test
+  void feature_depends2() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(null, Collections.emptySet(), true);
+    factoryOrder.add(bc("two", EMPTY_CLASSES, of(MyFeature.class)));
+    factoryOrder.add(bc("one", of(MyFeature.class), EMPTY_CLASSES));
+    factoryOrder.add(bc("three", of(MyFeature.class), EMPTY_CLASSES));
+    factoryOrder.orderModules();
+
+    assertThat(names(factoryOrder.factories())).containsExactly("one", "three", "two");
+  }
+
+  @Test
+  void name_requiresPackage() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(null, Collections.emptySet(), true);
+    factoryOrder.add(bc("1", EMPTY_CLASSES, new Class[0], of(Mod3.class)));
+    factoryOrder.add(bc("2", EMPTY_CLASSES, new Class[0], of(Mod4.class)));
+    factoryOrder.add(bc("3", of(Mod3.class), new Class[0], of(Mod4.class)));
+    factoryOrder.add(bc("4", of(Mod4.class), new Class[0]));
+
+    factoryOrder.orderModules();
+
+    assertThat(names(factoryOrder.factories())).containsExactly("4", "2", "3", "1");
+  }
+
+  @Test
+  void name_requiresPackage_mixed() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(null, Collections.emptySet(), true);
+    factoryOrder.add(bc("1", EMPTY_CLASSES, new Class[0], of(Mod3.class)));
+    factoryOrder.add(bc("2", EMPTY_CLASSES, of(Mod4.class), new Class[0]));
+    factoryOrder.add(bc("3", of(Mod3.class), new Class[0], of(Mod4.class)));
+    factoryOrder.add(bc("4", of(Mod4.class), new Class[0]));
+
+    factoryOrder.orderModules();
+
+    assertThat(names(factoryOrder.factories())).containsExactly("4", "2", "3", "1");
+  }
+
+  @Test
+  void missingRequiresPackage_expect_unsatisfiedRequiresPackages() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(null, Collections.emptySet(), false);
+    factoryOrder.add(bc("1", EMPTY_CLASSES, new Class[0], of(Mod3.class)));
+    factoryOrder.add(bc("2", EMPTY_CLASSES, of(Mod4.class), new Class[0]));
+    factoryOrder.add(bc("4", of(Mod4.class), new Class[0]));
+
+    assertThatThrownBy(factoryOrder::orderModules)
+        .isInstanceOf(IllegalStateException.class)
+        .hasMessageContaining(
+            "has unsatisfied requiresPackages [io.avaje.inject.LegacyBeanScopeBuilderTest$Mod3] ");
+  }
+
+  @Test
+  void missingRequires_expect_unsatisfiedRequires() {
+    DBeanScopeBuilder.FactoryOrder factoryOrder =
+        new DBeanScopeBuilder.FactoryOrder(null, Collections.emptySet(), false);
+    factoryOrder.add(bc("1", EMPTY_CLASSES, of(Mod3.class), new Class[0]));
+    factoryOrder.add(bc("2", EMPTY_CLASSES, of(Mod4.class), new Class[0]));
+    factoryOrder.add(bc("4", of(Mod4.class), new Class[0]));
+
+    assertThatThrownBy(factoryOrder::orderModules)
+        .isInstanceOf(IllegalStateException.class)
+        .hasMessageContaining(
+            "has unsatisfied requires [io.avaje.inject.LegacyBeanScopeBuilderTest$Mod3] ");
+  }
+
+  private List<String> names(List<AvajeModule> factories) {
+    return factories.stream().map(AvajeModule::toString).collect(Collectors.toList());
+  }
+
+  private TDModule bc(String name, Class<?>[] provides, Class<?>[] requires) {
+    return bc(name, provides, requires, new Class[0]);
+  }
+
+  private TDModule bc(
+      String name, Class<?>[] provides, Class<?>[] requires, Class<?>[] requiresPkg) {
+    return new TDModule(name, provides, requires, requiresPkg);
+  }
+
+  private static class TDModule implements Module {
+
+    final String name;
+    final Class<?>[] provides;
+    final Class<?>[] requires;
+    final Class<?>[] requiresPackages;
+
+    private TDModule(
+        String name, Class<?>[] provides, Class<?>[] requires, Class<?>[] requiresPackages) {
+      this.name = name;
+      this.provides = provides;
+      this.requires = requires;
+      this.requiresPackages = requiresPackages;
+    }
+
+    @Override
+    public String toString() {
+      return name;
+    }
+
+    @Override
+    public Class<?>[] provides() {
+      return provides;
+    }
+
+    @Override
+    public Class<?>[] classes() {
+      return new Class[0];
+    }
+
+    @Override
+    public Class<?>[] requires() {
+      return requires;
+    }
+
+    @Override
+    public Class<?>[] requiresPackages() {
+      return requiresPackages;
+    }
+
+    @Override
+    public void build(Builder parent) {}
+  }
+
+  Class<?>[] of(Class<?>... cls) {
+    return cls != null ? cls : new Class<?>[0];
+  }
+
+  class MyFeature {}
+
+  class FeatureA {}
+
+  class Mod3 {}
+
+  class Mod4 {}
+
+  static class TDBeanScope implements BeanScope {
+
+    final String containsType;
+
+    TDBeanScope(Type containsType) {
+      this.containsType = containsType.getTypeName();
+    }
+
+    @Override
+    public boolean contains(String type) {
+      return containsType.equals(type);
+    }
+
+    @Override
+    public <T> T get(Class<T> type) {
+      return null;
+    }
+
+    @Override
+    public <T> T get(Class<T> type, String name) {
+      return null;
+    }
+
+    @Override
+    public <T> T get(Type type, String name) {
+      return null;
+    }
+
+    @Override
+    public <T> Optional<T> getOptional(Class<T> type) {
+      return Optional.empty();
+    }
+
+    @Override
+    public <T> Optional<T> getOptional(Type type, String name) {
+      return Optional.empty();
+    }
+
+    @Override
+    public List<Object> listByAnnotation(Class<? extends Annotation> annotation) {
+      return null;
+    }
+
+    @Override
+    public <T> List<T> list(Class<T> type) {
+      return null;
+    }
+
+    @Override
+    public <T> List<T> list(Type type) {
+      return null;
+    }
+
+    @Override
+    public <T> List<T> listByPriority(Class<T> type) {
+      return null;
+    }
+
+    @Override
+    public <T> List<T> listByPriority(Class<T> type, Class<? extends Annotation> priority) {
+      return null;
+    }
+
+    @Override
+    public <T> Map<String, T> map(Type type) {
+      return Collections.emptyMap();
+    }
+
+    @Override
+    public List<BeanEntry> all() {
+      return null;
+    }
+
+    @Override
+    public boolean contains(Type type) {
+      return false;
+    }
+
+    @Override
+    public void close() {}
+  }
+}
diff --git a/inject/src/test/java/io/avaje/inject/spi/DContextEntryTest.java b/inject/src/test/java/io/avaje/inject/spi/DContextEntryTest.java
index 03e61d80..2eaca674 100644
--- a/inject/src/test/java/io/avaje/inject/spi/DContextEntryTest.java
+++ b/inject/src/test/java/io/avaje/inject/spi/DContextEntryTest.java
@@ -99,16 +99,16 @@ class DContextEntryTest {
   void getWithName_when_currentModule() {
 
     DContextEntry entry = new DContextEntry();
-    entry.add(DContextEntryBean.of("N1", "same", BeanEntry.NORMAL, Module.class));
+    entry.add(DContextEntryBean.of("N1", "same", BeanEntry.NORMAL, AvajeModule.class));
     entry.add(DContextEntryBean.of("N2", "same", BeanEntry.NORMAL, null));
     entry.add(DContextEntryBean.of("N3", "same", BeanEntry.NORMAL, OtherModule.class));
 
     assertEquals(entry.get("same", null), "N2");
-    assertEquals(entry.get("same", Module.class), "N1");
+    assertEquals(entry.get("same", AvajeModule.class), "N1");
     assertEquals(entry.get("same", OtherModule.class), "N3");
 
     assertEquals(entry.get(null, null), "N2");
-    assertEquals(entry.get(null, Module.class), "N1");
+    assertEquals(entry.get(null, AvajeModule.class), "N1");
     assertEquals(entry.get(null, OtherModule.class), "N3");
   }
 
@@ -116,16 +116,16 @@ class DContextEntryTest {
   void getWithoutName_when_currentModule() {
 
     DContextEntry entry = new DContextEntry();
-    entry.add(DContextEntryBean.of("N1", null, BeanEntry.NORMAL, Module.class));
+    entry.add(DContextEntryBean.of("N1", null, BeanEntry.NORMAL, AvajeModule.class));
     entry.add(DContextEntryBean.of("N2", null, BeanEntry.NORMAL, null));
     entry.add(DContextEntryBean.of("N3", null, BeanEntry.NORMAL, OtherModule.class));
 
     assertEquals(entry.get(null, null), "N2");
-    assertEquals(entry.get(null, Module.class), "N1");
+    assertEquals(entry.get(null, AvajeModule.class), "N1");
     assertEquals(entry.get(null, OtherModule.class), "N3");
 
     assertNull(entry.get("notThere", null));
-    assertNull(entry.get("notThere", Module.class));
+    assertNull(entry.get("notThere", AvajeModule.class));
     assertNull(entry.get("notThere", OtherModule.class));
   }
 
@@ -133,12 +133,12 @@ class DContextEntryTest {
   void getWithName_expect_matchOnName() {
 
     DContextEntry entry = new DContextEntry();
-    entry.add(DContextEntryBean.of("N1", "same", BeanEntry.NORMAL, Module.class));
+    entry.add(DContextEntryBean.of("N1", "same", BeanEntry.NORMAL, AvajeModule.class));
     entry.add(DContextEntryBean.of("N2", null, BeanEntry.NORMAL, null));
     entry.add(DContextEntryBean.of("N3", null, BeanEntry.NORMAL, OtherModule.class));
 
     assertEquals(entry.get("same", null), "N1");
-    assertEquals(entry.get("same", Module.class), "N1");
+    assertEquals(entry.get("same", AvajeModule.class), "N1");
     assertEquals(entry.get("same", OtherModule.class), "N1");
   }
 
@@ -146,12 +146,12 @@ class DContextEntryTest {
   void getWithoutName_expect_matchOnNoName() {
 
     DContextEntry entry = new DContextEntry();
-    entry.add(DContextEntryBean.of("N1", null, BeanEntry.NORMAL, Module.class));
+    entry.add(DContextEntryBean.of("N1", null, BeanEntry.NORMAL, AvajeModule.class));
     entry.add(DContextEntryBean.of("N2", "same", BeanEntry.NORMAL, null));
     entry.add(DContextEntryBean.of("N3", "same", BeanEntry.NORMAL, OtherModule.class));
 
     assertEquals(entry.get(null, null), "N1");
-    assertEquals(entry.get(null, Module.class), "N1");
+    assertEquals(entry.get(null, AvajeModule.class), "N1");
     assertEquals(entry.get(null, OtherModule.class), "N1");
   }
 
@@ -159,11 +159,11 @@ class DContextEntryTest {
   void when_noQualifier_expect_matchedToNoQualider() {
 
     DContextEntry entry = new DContextEntry();
-    entry.add(DContextEntryBean.of("N1", null, BeanEntry.NORMAL, Module.class));
-    entry.add(DContextEntryBean.of("N2", "myName", BeanEntry.NORMAL, Module.class));
+    entry.add(DContextEntryBean.of("N1", null, BeanEntry.NORMAL, AvajeModule.class));
+    entry.add(DContextEntryBean.of("N2", "myName", BeanEntry.NORMAL, AvajeModule.class));
 
-    assertEquals(entry.get("myName", Module.class), "N2");
-    assertEquals(entry.get(null, Module.class), "N1");
+    assertEquals(entry.get("myName", AvajeModule.class), "N2");
+    assertEquals(entry.get(null, AvajeModule.class), "N1");
   }
 
   @Test
@@ -173,11 +173,11 @@ class DContextEntryTest {
     entry.add(DContextEntryBean.of("N1", null, BeanEntry.NORMAL, null));
     entry.add(DContextEntryBean.of("N2", "myName", BeanEntry.NORMAL, null));
 
-    assertEquals(entry.get("myName", Module.class), "N2");
-    assertEquals(entry.get(null, Module.class), "N1");
+    assertEquals(entry.get("myName", AvajeModule.class), "N2");
+    assertEquals(entry.get(null, AvajeModule.class), "N1");
   }
 
-  class OtherModule implements Module {
+  class OtherModule implements AvajeModule {
     @Override
     public Class<?>[] classes() {
       return new Class[0];