You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2021/07/26 01:12:48 UTC

[logging-log4j2] 02/05: Add type hierarchy data to plugin modules

This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch mean-bean-machine
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit c3c88f52448f047d7535186ce4e226d4ea6dff7a
Author: Matt Sicker <bo...@gmail.com>
AuthorDate: Sat Jul 24 18:59:14 2021 -0500

    Add type hierarchy data to plugin modules
    
    This also renames BeanInfoService to PluginModule along with some pom simplifications discovered while debugging MCOMPILER-461.
---
 log4j-core/pom.xml                                 |  35 +---
 log4j-core/src/main/java9/module-info.java         |  12 +-
 log4j-plugins/pom.xml                              |  80 +--------
 .../log4j/plugins/di/spi/BeanInfoService.java      |  52 ------
 .../logging/log4j/plugins/di/spi/PluginModule.java |  54 +++++++
 .../log4j/plugins/processor/BeanProcessor.java     | 179 ++++++++++++---------
 log4j-plugins/src/main/java9/module-info.java      |  12 +-
 log4j-plugins/src/test/java-test9/module-info.java |   5 +-
 .../log4j/plugins/processor/BeanProcessorTest.java |  31 ++--
 log4j-plugins/src/test/java9/module-info.java      |  12 +-
 pom.xml                                            |   2 +-
 11 files changed, 203 insertions(+), 271 deletions(-)

diff --git a/log4j-core/pom.xml b/log4j-core/pom.xml
index 8402405..31700a0 100644
--- a/log4j-core/pom.xml
+++ b/log4j-core/pom.xml
@@ -330,7 +330,7 @@
                   <includes>
                     <include>module-info.class</include>
                     <include>**/Log4jPlugins.class</include>
-                    <include>**/Log4jBeanInfo.class</include>
+                    <include>**/Log4jModule.class</include>
                   </includes>
                 </fileset>
                 <fileset>
@@ -353,13 +353,6 @@
               <goal>compile</goal>
             </goals>
             <phase>compile</phase>
-            <configuration combine.self="override">
-              <source>${maven.compiler.source}</source>
-              <target>${maven.compiler.target}</target>
-              <release>${maven.compiler.release}</release>
-              <forceJavacCompilerUse>true</forceJavacCompilerUse>
-              <parameters>true</parameters>
-            </configuration>
           </execution>
           <execution>
             <!-- compile the module-info.java -->
@@ -369,11 +362,6 @@
             </goals>
             <phase>compile</phase>
             <configuration combine.self="override">
-              <source>${maven.compiler.source}</source>
-              <target>${maven.compiler.target}</target>
-              <release>${maven.compiler.release}</release>
-              <forceJavacCompilerUse>true</forceJavacCompilerUse>
-              <parameters>true</parameters>
               <compileSourceRoots>
                 <compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
               </compileSourceRoots>
@@ -387,15 +375,10 @@
             </goals>
             <phase>compile</phase>
             <configuration>
-              <source>${maven.compiler.source}</source>
-              <target>${maven.compiler.target}</target>
-              <release>${maven.compiler.release}</release>
               <compileSourceRoots>
                 <compileSourceRoot>${project.basedir}/src/test/java-test</compileSourceRoot>
                 <compileSourceRoot>${project.basedir}/src/test/java-test9</compileSourceRoot>
               </compileSourceRoots>
-              <forceJavacCompilerUse>true</forceJavacCompilerUse>
-              <parameters>true</parameters>
             </configuration>
           </execution>
           <execution>
@@ -406,14 +389,9 @@
             </goals>
             <phase>process-test-sources</phase>
             <configuration>
-              <source>${maven.compiler.source}</source>
-              <target>${maven.compiler.target}</target>
-              <release>${maven.compiler.release}</release>
-              <forceJavacCompilerUse>true</forceJavacCompilerUse>
-              <parameters>true</parameters>
-              <compilerArgs>
-                <arg>-ApluginPackage=org.apache.logging.log4j.core.test</arg>
-              </compilerArgs>
+              <compilerArguments>
+                <ApluginPackage>org.apache.logging.log4j.core.test</ApluginPackage>
+              </compilerArguments>
               <compileSourceRoots>
                 <compileSourceRoot>${project.basedir}/src/test/java</compileSourceRoot>
                 <compileSourceRoot>${project.basedir}/src/test/java-test</compileSourceRoot>
@@ -427,11 +405,6 @@
               <goal>testCompile</goal>
             </goals>
             <configuration>
-              <source>${maven.compiler.source}</source>
-              <target>${maven.compiler.target}</target>
-              <release>${maven.compiler.release}</release>
-              <forceJavacCompilerUse>true</forceJavacCompilerUse>
-              <parameters>true</parameters>
               <compileSourceRoots>
                 <compileSourceRoot>${project.basedir}/src/test/java9</compileSourceRoot>
               </compileSourceRoots>
diff --git a/log4j-core/src/main/java9/module-info.java b/log4j-core/src/main/java9/module-info.java
index d4b3d93..890f348 100644
--- a/log4j-core/src/main/java9/module-info.java
+++ b/log4j-core/src/main/java9/module-info.java
@@ -81,8 +81,12 @@ module org.apache.logging.log4j.core {
     requires transitive org.fusesource.jansi;
     uses org.apache.logging.log4j.core.util.ContextDataProvider;
     uses org.apache.logging.log4j.core.util.WatchEventService;
-    provides org.apache.logging.log4j.message.ThreadDumpMessage.ThreadInfoFactory with org.apache.logging.log4j.core.message.ExtendedThreadInfoFactory;
-    provides org.apache.logging.log4j.core.util.ContextDataProvider with org.apache.logging.log4j.core.impl.ThreadContextDataProvider;
-    provides org.apache.logging.log4j.spi.Provider with org.apache.logging.log4j.core.impl.Log4jProvider;
-    provides org.apache.logging.log4j.plugins.processor.PluginService with org.apache.logging.log4j.core.plugins.Log4jPlugins;
+    provides org.apache.logging.log4j.message.ThreadDumpMessage.ThreadInfoFactory with
+            org.apache.logging.log4j.core.message.ExtendedThreadInfoFactory;
+    provides org.apache.logging.log4j.core.util.ContextDataProvider with
+            org.apache.logging.log4j.core.impl.ThreadContextDataProvider;
+    provides org.apache.logging.log4j.spi.Provider with
+            org.apache.logging.log4j.core.impl.Log4jProvider;
+    provides org.apache.logging.log4j.plugins.processor.PluginService with
+            org.apache.logging.log4j.core.plugins.Log4jPlugins;
 }
diff --git a/log4j-plugins/pom.xml b/log4j-plugins/pom.xml
index c562089..0bd5930 100644
--- a/log4j-plugins/pom.xml
+++ b/log4j-plugins/pom.xml
@@ -105,7 +105,7 @@
                   <includes>
                     <include>module-info.class</include>
                     <include>**/Log4jPlugins.class</include>
-                    <include>**/Log4jBeanInfo.class</include>
+                    <include>**/Log4jModule.class</include>
                   </includes>
                 </fileset>
                 <fileset>
@@ -140,14 +140,11 @@
             </goals>
             <phase>generate-sources</phase>
             <configuration combine.self="override">
-              <source>${maven.compiler.source}</source>
-              <target>${maven.compiler.target}</target>
               <proc>only</proc>
               <annotationProcessors>
                 <annotationProcessor>org.apache.logging.log4j.plugins.processor.PluginProcessor</annotationProcessor>
                 <annotationProcessor>org.apache.logging.log4j.plugins.processor.BeanProcessor</annotationProcessor>
               </annotationProcessors>
-              <parameters>true</parameters>
             </configuration>
           </execution>
           <execution>
@@ -158,8 +155,6 @@
             </goals>
             <phase>generate-sources</phase>
             <configuration combine.self="override">
-              <source>${maven.compiler.source}</source>
-              <target>${maven.compiler.target}</target>
               <proc>only</proc>
               <annotationProcessors>
                 <annotationProcessor>org.apache.logging.log4j.plugins.processor.PluginProcessor</annotationProcessor>
@@ -168,7 +163,6 @@
               <compileSourceRoots>
                 <compileSourceRoot>${project.basedir}/src/test/java-test</compileSourceRoot>
               </compileSourceRoots>
-              <parameters>true</parameters>
             </configuration>
           </execution>
           <execution>
@@ -179,8 +173,6 @@
             </goals>
             <phase>generate-sources</phase>
             <configuration combine.self="override">
-              <source>${maven.compiler.source}</source>
-              <target>${maven.compiler.target}</target>
               <proc>only</proc>
               <annotationProcessors>
                 <annotationProcessor>org.apache.logging.log4j.plugins.processor.PluginProcessor</annotationProcessor>
@@ -195,7 +187,6 @@
               </compileSourceRoots>
               <generatedTestSourcesDirectory>${project.build.directory}/generated-test-sources/unit-test-annotations</generatedTestSourcesDirectory>
               <outputDirectory>${project.build.directory}/unit-test-classes</outputDirectory>
-              <parameters>true</parameters>
             </configuration>
           </execution>
           <execution>
@@ -205,37 +196,6 @@
               <goal>compile</goal>
             </goals>
             <configuration combine.self="override">
-              <source>${maven.compiler.source}</source>
-              <target>${maven.compiler.target}</target>
-              <release>${maven.compiler.release}</release>
-              <showDeprecation>true</showDeprecation>
-              <showWarnings>true</showWarnings>
-              <encoding>UTF-8</encoding>
-              <fork>true</fork>
-              <meminitial>256</meminitial>
-              <maxmem>1024</maxmem>
-              <compilerArgs>
-                <arg>-XDcompilePolicy=simple</arg>
-                <arg>-Xplugin:ErrorProne</arg>
-                <!--
-                https://errorprone.info/docs/installation
-                in Java 16+, https://openjdk.java.net/jeps/396 encapsulates internals that errorprone needs
-                -->
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
-                <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
-                <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
-              </compilerArgs>
-              <compilerArguments>
-                <Xmaxwarns>10000</Xmaxwarns>
-                <Xlint />
-              </compilerArguments>
               <annotationProcessorPaths>
                 <path>
                   <groupId>com.google.errorprone</groupId>
@@ -243,8 +203,6 @@
                   <version>${errorprone.version}</version>
                 </path>
               </annotationProcessorPaths>
-              <forceJavacCompilerUse>true</forceJavacCompilerUse>
-              <parameters>true</parameters>
               <compileSourceRoots>
                 <compileSourceRoot>${project.basedir}/src/main/java</compileSourceRoot>
                 <compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
@@ -259,14 +217,11 @@
             </goals>
             <phase>process-classes</phase>
             <configuration combine.self="override">
-              <source>${maven.compiler.source}</source>
-              <target>${maven.compiler.target}</target>
               <proc>none</proc>
               <compileSourceRoots>
                 <compileSourceRoot>${project.basedir}/src/test/java-test</compileSourceRoot>
                 <compileSourceRoot>${project.basedir}/src/test/java-test9</compileSourceRoot>
               </compileSourceRoots>
-              <parameters>true</parameters>
             </configuration>
           </execution>
           <execution>
@@ -276,39 +231,6 @@
               <goal>testCompile</goal>
             </goals>
             <configuration combine.self="override">
-              <source>${maven.compiler.source}</source>
-              <target>${maven.compiler.target}</target>
-              <release>${maven.compiler.release}</release>
-              <showDeprecation>true</showDeprecation>
-              <showWarnings>true</showWarnings>
-              <encoding>UTF-8</encoding>
-              <fork>true</fork>
-              <meminitial>256</meminitial>
-              <maxmem>1024</maxmem>
-              <compilerArgs>
-                <arg>-XDcompilePolicy=simple</arg>
-                <arg>-Xplugin:ErrorProne</arg>
-                <!--
-                https://errorprone.info/docs/installation
-                in Java 16+, https://openjdk.java.net/jeps/396 encapsulates internals that errorprone needs
-                -->
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
-                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
-                <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
-                <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
-              </compilerArgs>
-              <compilerArguments>
-                <Xmaxwarns>10000</Xmaxwarns>
-                <Xlint />
-              </compilerArguments>
-              <forceJavacCompilerUse>true</forceJavacCompilerUse>
-              <parameters>true</parameters>
               <annotationProcessorPaths>
                 <path>
                   <groupId>com.google.errorprone</groupId>
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/spi/BeanInfoService.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/spi/BeanInfoService.java
deleted file mode 100644
index f7f45e1..0000000
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/spi/BeanInfoService.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-
-package org.apache.logging.log4j.plugins.di.spi;
-
-import java.util.List;
-import java.util.Map;
-
-public abstract class BeanInfoService {
-    private final List<String> injectableClassNames;
-    private final List<String> producibleClassNames;
-    private final List<String> destructibleClassNames;
-    private final Map<String, List<String>> pluginCategories;
-
-    protected BeanInfoService(final List<String> injectableClassNames, final List<String> producibleClassNames,
-                              final List<String> destructibleClassNames, final Map<String, List<String>> pluginCategories) {
-        this.injectableClassNames = injectableClassNames;
-        this.producibleClassNames = producibleClassNames;
-        this.destructibleClassNames = destructibleClassNames;
-        this.pluginCategories = pluginCategories;
-    }
-
-    public List<String> getInjectableClassNames() {
-        return injectableClassNames;
-    }
-
-    public List<String> getProducibleClassNames() {
-        return producibleClassNames;
-    }
-
-    public List<String> getDestructibleClassNames() {
-        return destructibleClassNames;
-    }
-
-    public Map<String, List<String>> getPluginCategories() {
-        return pluginCategories;
-    }
-}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/spi/PluginModule.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/spi/PluginModule.java
new file mode 100644
index 0000000..279be74
--- /dev/null
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/spi/PluginModule.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.plugins.di.spi;
+
+import java.util.Map;
+import java.util.Set;
+
+public abstract class PluginModule {
+    private final Map<String, Set<String>> injectionBeans;
+    private final Map<String, Set<String>> producerBeans;
+    private final Set<String> destructorBeans;
+    private final Map<String, Set<String>> pluginBeans;
+
+    protected PluginModule(final Map<String, Set<String>> injectionBeans,
+                           final Map<String, Set<String>> producerBeans,
+                           final Set<String> destructorBeans,
+                           final Map<String, Set<String>> pluginBeans) {
+        this.injectionBeans = injectionBeans;
+        this.producerBeans = producerBeans;
+        this.destructorBeans = destructorBeans;
+        this.pluginBeans = pluginBeans;
+    }
+
+    public Map<String, Set<String>> getInjectionBeans() {
+        return injectionBeans;
+    }
+
+    public Map<String, Set<String>> getProducerBeans() {
+        return producerBeans;
+    }
+
+    public Set<String> getDestructorBeans() {
+        return destructorBeans;
+    }
+
+    public Map<String, Set<String>> getPluginBeans() {
+        return pluginBeans;
+    }
+}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/BeanProcessor.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/BeanProcessor.java
index 013bab6..d2f1386 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/BeanProcessor.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/BeanProcessor.java
@@ -21,7 +21,6 @@ import org.apache.logging.log4j.plugins.di.Disposes;
 import org.apache.logging.log4j.plugins.di.Inject;
 import org.apache.logging.log4j.plugins.di.Producer;
 import org.apache.logging.log4j.plugins.di.Qualifier;
-import org.apache.logging.log4j.util.Strings;
 
 import javax.annotation.processing.AbstractProcessor;
 import javax.annotation.processing.RoundEnvironment;
@@ -35,30 +34,28 @@ import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
 import javax.lang.model.util.ElementKindVisitor9;
 import javax.lang.model.util.Elements;
 import javax.lang.model.util.SimpleAnnotationValueVisitor9;
 import javax.lang.model.util.Types;
-import javax.tools.FileObject;
-import javax.tools.JavaFileObject;
 import javax.tools.StandardLocation;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.UncheckedIOException;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 // TODO: migrate to separate maven module between log4j-plugins and log4j-core
 @SupportedAnnotationTypes({"org.apache.logging.log4j.plugins.*", "org.apache.logging.log4j.core.config.plugins.*"})
 @SupportedOptions("pluginPackage")
 public class BeanProcessor extends AbstractProcessor {
-    public static final String BEAN_INFO_SERVICE_FILE = "META-INF/services/org.apache.logging.log4j.plugins.di.spi.BeanInfoService";
+    public static final String PLUGIN_MODULE_SERVICE_FILE = "META-INF/services/org.apache.logging.log4j.plugins.di.spi.PluginModule";
 
     public BeanProcessor() {
     }
@@ -214,45 +211,50 @@ public class BeanProcessor extends AbstractProcessor {
         final var pluginAnnotationVisitor = new PluginAnnotationVisitor();
         roundEnv.getElementsAnnotatedWithAny(pluginAnnotations).forEach(pluginAnnotationVisitor::visit);
 
-        final Set<ExecutableElement> producerMethods = producesAnnotationVisitor.producerMethods;
-        final Set<VariableElement> producerFields = producesAnnotationVisitor.producerFields;
-        final Set<ExecutableElement> disposesMethods = disposesAnnotationVisitor.disposesMethods;
-        final Set<TypeElement> injectableClasses = injectAnnotationVisitor.injectableClasses;
-        final Set<TypeElement> implicitInjectableClasses = qualifiedAnnotationVisitor.injectableClasses;
-        final Map<String, Set<TypeElement>> pluginCategories = pluginAnnotationVisitor.pluginCategories;
         final Set<PackageElement> packageElements = new HashSet<>();
 
         final Elements elements = processingEnv.getElementUtils();
-        final Set<CharSequence> producibleClassNames = Stream.concat(
-                producerMethods.stream()
-                        .map(e -> (TypeElement) e.getEnclosingElement())
-                        .peek(e -> packageElements.add(elements.getPackageOf(e)))
-                        .map(elements::getBinaryName),
-                producerFields.stream()
-                        .map(e -> (TypeElement) e.getEnclosingElement())
-                        .peek(e -> packageElements.add(elements.getPackageOf(e)))
-                        .map(elements::getBinaryName))
-                .collect(Collectors.toSet());
-        final Set<CharSequence> destructibleClassNames = disposesMethods.stream()
+        final Map<String, Set<String>> producerBeans = new HashMap<>();
+        for (final ExecutableElement producerMethod : producesAnnotationVisitor.producerMethods) {
+            final TypeElement declaringType = (TypeElement) producerMethod.getEnclosingElement();
+            packageElements.add(elements.getPackageOf(declaringType));
+            final String declaringClassName = elements.getBinaryName(declaringType).toString();
+            final Set<String> classNameHierarchy = getClassNameHierarchy(producerMethod.getReturnType());
+            producerBeans.put(declaringClassName, classNameHierarchy);
+        }
+        for (final VariableElement producerField : producesAnnotationVisitor.producerFields) {
+            final TypeElement declaringType = (TypeElement) producerField.getEnclosingElement();
+            packageElements.add(elements.getPackageOf(declaringType));
+            final String declaringClassName = elements.getBinaryName(declaringType).toString();
+            final Set<String> classNameHierarchy = getClassNameHierarchy(producerField.asType());
+            producerBeans.put(declaringClassName, classNameHierarchy);
+        }
+
+        final Set<CharSequence> destructibleClassNames = disposesAnnotationVisitor.disposesMethods.stream()
                 .map(e -> (TypeElement) e.getEnclosingElement())
                 .peek(e -> packageElements.add(elements.getPackageOf(e)))
                 .map(elements::getBinaryName)
                 .collect(Collectors.toSet());
-        final Set<CharSequence> injectableClassNames = Stream.concat(
-                injectableClasses.stream()
-                        .peek(e -> packageElements.add(elements.getPackageOf(e)))
-                        .map(elements::getBinaryName),
-                implicitInjectableClasses.stream()
-                        .peek(e -> packageElements.add(elements.getPackageOf(e)))
-                        .map(elements::getBinaryName))
-                .collect(Collectors.toSet());
-        final Map<String, List<CharSequence>> pluginClassNames = pluginCategories.entrySet().stream().collect(
-                Collectors.toMap(Map.Entry::getKey,
-                        entry -> entry.getValue().stream()
-                                .peek(el -> packageElements.add(elements.getPackageOf(el)))
-                                .map(elements::getBinaryName)
-                                .sorted(CharSequence::compare)
-                                .collect(Collectors.toList())));
+
+        final Map<String, Set<String>> injectionBeans = new HashMap<>();
+        final Set<TypeElement> injectionClasses = new HashSet<>(injectAnnotationVisitor.injectableClasses);
+        injectionClasses.addAll(qualifiedAnnotationVisitor.injectableClasses);
+        for (final TypeElement injectableClass : injectionClasses) {
+            packageElements.add(elements.getPackageOf(injectableClass));
+            final String declaringClassName = elements.getBinaryName(injectableClass).toString();
+            final Set<String> classNameHierarchy = getClassNameHierarchy(injectableClass.asType());
+            injectionBeans.put(declaringClassName, classNameHierarchy);
+        }
+
+        final Map<String, Set<String>> pluginBeans = pluginAnnotationVisitor.pluginCategories
+                .values()
+                .stream()
+                .flatMap(Set::stream)
+                .peek(typeElement -> packageElements.add(elements.getPackageOf(typeElement)))
+                .collect(Collectors.toMap(
+                        typeElement -> elements.getBinaryName(typeElement).toString(),
+                        typeElement -> getClassNameHierarchy(typeElement.asType())
+                ));
 
         String packageName = processingEnv.getOptions().get("pluginPackage");
         if (packageName == null) {
@@ -263,66 +265,97 @@ public class BeanProcessor extends AbstractProcessor {
                     .orElseThrow()
                     .toString();
         }
+        String className = processingEnv.getOptions().getOrDefault("pluginClassName", "Log4jModule");
         try {
-            writeBeanInfoServiceFile(packageName);
-            writeBeanInfoServiceClass(packageName, injectableClassNames, producibleClassNames, destructibleClassNames, pluginClassNames);
+            writePluginModule(packageName, className, injectionBeans, producerBeans, destructibleClassNames, pluginBeans);
             return false;
         } catch (IOException e) {
             throw new UncheckedIOException(e);
         }
     }
 
-    private void writeBeanInfoServiceFile(final String packageName) throws IOException {
-        final FileObject fileObject = processingEnv.getFiler()
-                .createResource(StandardLocation.CLASS_OUTPUT, "", BEAN_INFO_SERVICE_FILE);
-        try (PrintWriter out = new PrintWriter(fileObject.openWriter())) {
-            out.println(packageName + ".plugins.Log4jBeanInfo");
+    private void writePluginModule(final CharSequence packageName, final CharSequence className,
+                                   final Map<String, Set<String>> injectionBeans,
+                                   final Map<String, Set<String>> producerBeans,
+                                   final Set<CharSequence> destructorBeans,
+                                   final Map<String, Set<String>> pluginBeans) throws IOException {
+        try (final PrintWriter out = new PrintWriter(processingEnv.getFiler().createResource(
+                StandardLocation.CLASS_OUTPUT, "", PLUGIN_MODULE_SERVICE_FILE).openWriter())) {
+            out.println(packageName + ".plugins." + className);
         }
-    }
-
-    private void writeBeanInfoServiceClass(final String packageName, final Set<CharSequence> injectableClassNames,
-                                           final Set<CharSequence> producibleClassNames,
-                                           final Set<CharSequence> destructibleClassNames,
-                                           final Map<String, List<CharSequence>> pluginClassNames)
-            throws IOException {
-        final JavaFileObject sourceFile = processingEnv.getFiler()
-                .createSourceFile(packageName + ".plugins.Log4jBeanInfo");
-        try (final PrintWriter out = new PrintWriter(sourceFile.openWriter())) {
+        try (final PrintWriter out = new PrintWriter(processingEnv.getFiler().createSourceFile(
+                packageName + ".plugins." + className).openWriter())) {
             out.println("package " + packageName + ".plugins;");
             out.println();
-            out.println("import java.util.List;");
-            out.println("import java.util.Map;");
+            out.println("import java.util.*;");
+            out.println();
+            out.println("import org.apache.logging.log4j.plugins.di.spi.PluginModule;");
             out.println();
             out.println("@javax.annotation.processing.Generated(\"" + getClass().getName() + "\")");
-            out.println("public class Log4jBeanInfo extends org.apache.logging.log4j.plugins.di.spi.BeanInfoService {");
+            out.println("public class " + className + " extends PluginModule {");
             out.println();
-            out.println("  private static final List<String> INJECTABLE = List.of(" + getListOfNames(injectableClassNames) + ");");
+            out.println("  private static final Map<String, Set<String>> INJECT =");
+            out.println("    new TreeMap<>(Map.ofEntries(" + getEntries(injectionBeans) + "));");
             out.println();
-            out.println("  private static final List<String> PRODUCIBLE = List.of(" + getListOfNames(producibleClassNames) + ");");
+            out.println("  private static final Map<String, Set<String>> PRODUCE =");
+            out.println("    new TreeMap<>(Map.ofEntries(" + getEntries(producerBeans) + "));");
             out.println();
-            out.println("  private static final List<String> DESTRUCTIBLE = List.of(" + getListOfNames(destructibleClassNames) + ");");
+            out.println("  private static final Set<String> DESTROY = new TreeSet<>(Set.of(" + destructorBeans.stream().sorted(CharSequence::compare).collect(Collectors.joining("\",\n\"", "\n\"", "\"\n")) + "));");
             out.println();
-            out.println("  private static final Map<String, List<String>> PLUGIN_CATEGORIES = Map.of(" + getMapOfPluginNames(pluginClassNames) + ");");
+            out.println("  private static final Map<String, Set<String>> PLUGINS =");
+            out.println("    new TreeMap<>(Map.ofEntries(" + getEntries(pluginBeans) + "));");
             out.println();
-            out.println("  public Log4jBeanInfo() {");
-            out.println("    super(INJECTABLE, PRODUCIBLE, DESTRUCTIBLE, PLUGIN_CATEGORIES);");
+            out.println("  public " + className + "() {");
+            out.println("    super(INJECT, PRODUCE, DESTROY, PLUGINS);");
             out.println("  }");
             out.println();
             out.println("}");
         }
     }
 
-    private static String getListOfNames(final Set<CharSequence> names) {
-        return names.isEmpty() ? Strings.EMPTY : names.stream().sorted(CharSequence::compare).collect(
-                Collectors.joining("\",\n    \"", "\n    \"", "\"\n  "));
+    private static String getEntries(final Map<String, Set<String>> beans) {
+        return beans.entrySet().stream()
+                .sorted(Map.Entry.comparingByKey())
+                .map(e -> "Map.entry(\"" + e.getKey() + "\", new TreeSet<>(Set.of(" + e.getValue().stream().sorted().collect(Collectors.joining("\", \"", "\"", "\"")) + ")))")
+                .collect(Collectors.joining(",\n", "\n", "\n"));
+    }
+
+    private Set<String> getClassNameHierarchy(final TypeMirror base) {
+        final Set<String> hierarchy = new TreeSet<>();
+        walkClassHierarchy(base, hierarchy);
+        return hierarchy;
     }
 
-    private static String getMapOfPluginNames(final Map<String, List<CharSequence>> pluginClassNames) {
-        return pluginClassNames.isEmpty() ? Strings.EMPTY : pluginClassNames.entrySet()
-                .stream()
-                .sorted(Map.Entry.comparingByKey())
-                .map(e -> '"' + e.getKey() + "\", List.of(" + e.getValue().stream().collect(Collectors.joining("\",\n      \"", "\n      \"", "\"\n    ")) + ')')
-                .collect(Collectors.joining(",\n    ", "\n    ", "\n  "));
+    private void walkClassHierarchy(final TypeMirror base, final Set<String> encountered) {
+        final Types types = processingEnv.getTypeUtils();
+        final Elements elements = processingEnv.getElementUtils();
+        final Element element = types.asElement(base);
+        if (element != null) {
+            element.accept(new ElementKindVisitor9<Void, Void>() {
+                @Override
+                public Void visitTypeAsClass(final TypeElement e, final Void unused) {
+                    if (!elements.getPackageOf(e).getQualifiedName().contentEquals("java.lang")) {
+                        encountered.add(elements.getBinaryName(e).toString());
+                    }
+                    return null;
+                }
+
+                @Override
+                public Void visitTypeAsEnum(final TypeElement e, final Void unused) {
+                    encountered.add(elements.getBinaryName(e).toString());
+                    return null;
+                }
+
+                @Override
+                public Void visitTypeAsInterface(final TypeElement e, final Void unused) {
+                    encountered.add(elements.getBinaryName(e).toString());
+                    return null;
+                }
+            }, null);
+        }
+        for (final TypeMirror directSupertype : types.directSupertypes(base)) {
+            walkClassHierarchy(directSupertype, encountered);
+        }
     }
 
     private static CharSequence commonPrefix(final CharSequence str1, final CharSequence str2) {
diff --git a/log4j-plugins/src/main/java9/module-info.java b/log4j-plugins/src/main/java9/module-info.java
index 4506235..01e587d 100644
--- a/log4j-plugins/src/main/java9/module-info.java
+++ b/log4j-plugins/src/main/java9/module-info.java
@@ -32,10 +32,14 @@ module org.apache.logging.log4j.plugins {
     requires transitive org.apache.logging.log4j;
     requires transitive org.osgi.framework;
 
-    provides org.apache.logging.log4j.plugins.processor.PluginService with org.apache.logging.log4j.plugins.convert.plugins.Log4jPlugins;
-    provides org.apache.logging.log4j.plugins.di.spi.BeanInfoService with org.apache.logging.log4j.plugins.convert.plugins.Log4jBeanInfo;
-    provides javax.annotation.processing.Processor with org.apache.logging.log4j.plugins.processor.PluginProcessor, org.apache.logging.log4j.plugins.processor.BeanProcessor;
+    provides org.apache.logging.log4j.plugins.processor.PluginService with
+            org.apache.logging.log4j.plugins.convert.plugins.Log4jPlugins;
+    provides org.apache.logging.log4j.plugins.di.spi.PluginModule with
+            org.apache.logging.log4j.plugins.convert.plugins.Log4jModule;
+    provides javax.annotation.processing.Processor with
+            org.apache.logging.log4j.plugins.processor.PluginProcessor,
+            org.apache.logging.log4j.plugins.processor.BeanProcessor;
 
     uses org.apache.logging.log4j.plugins.processor.PluginService;
-//    uses org.apache.logging.log4j.plugins.di.spi.BeanInfoService;
+//    uses org.apache.logging.log4j.plugins.di.spi.PluginModule;
 }
diff --git a/log4j-plugins/src/test/java-test9/module-info.java b/log4j-plugins/src/test/java-test9/module-info.java
index 529310c..3ac8a6a 100644
--- a/log4j-plugins/src/test/java-test9/module-info.java
+++ b/log4j-plugins/src/test/java-test9/module-info.java
@@ -4,5 +4,8 @@ module org.apache.logging.log4j.plugins.test {
     requires org.apache.logging.log4j;
     requires org.apache.logging.log4j.plugins;
 
-    provides org.apache.logging.log4j.plugins.processor.PluginService with org.apache.logging.log4j.plugins.test.validation.plugins.Log4jPlugins;
+    provides org.apache.logging.log4j.plugins.processor.PluginService with
+            org.apache.logging.log4j.plugins.test.validation.plugins.Log4jPlugins;
+    provides org.apache.logging.log4j.plugins.di.spi.PluginModule with
+            org.apache.logging.log4j.plugins.test.validation.plugins.Log4jModule;
 }
diff --git a/log4j-plugins/src/test/java/org/apache/logging/log4j/plugins/processor/BeanProcessorTest.java b/log4j-plugins/src/test/java/org/apache/logging/log4j/plugins/processor/BeanProcessorTest.java
index b63070c..7afe944 100644
--- a/log4j-plugins/src/test/java/org/apache/logging/log4j/plugins/processor/BeanProcessorTest.java
+++ b/log4j-plugins/src/test/java/org/apache/logging/log4j/plugins/processor/BeanProcessorTest.java
@@ -17,38 +17,25 @@
 
 package org.apache.logging.log4j.plugins.processor;
 
-import org.apache.logging.log4j.plugins.di.spi.BeanInfoService;
+import org.apache.logging.log4j.plugins.di.spi.PluginModule;
 import org.junit.jupiter.api.Test;
 
-import java.util.List;
 import java.util.ServiceLoader;
 
-import static org.junit.jupiter.api.Assertions.assertNotEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class BeanProcessorTest {
     @Test
-    void canLoadTestCategory() {
-        final BeanInfoService service = ServiceLoader.load(BeanInfoService.class, getClass().getClassLoader())
-                .findFirst()
-                .orElseThrow();
-        final List<String> testPlugins = service.getPluginCategories().get("Test");
-        assertNotNull(testPlugins);
-        assertNotEquals(0, testPlugins.size());
-        assertTrue(testPlugins.stream().anyMatch(name -> name.equals(FakePlugin.class.getName())));
-    }
-
-    @Test
     void smokeTests() {
-        final BeanInfoService service = ServiceLoader.load(BeanInfoService.class, getClass().getClassLoader())
+        final PluginModule service = ServiceLoader.load(PluginModule.class, getClass().getClassLoader())
                 .findFirst()
                 .orElseThrow();
-        assertTrue(service.getInjectableClassNames().stream().anyMatch(name -> name.equals("org.apache.logging.log4j.plugins.test.validation.ExampleBean")));
-        assertTrue(service.getInjectableClassNames().stream().anyMatch(name -> name.equals("org.apache.logging.log4j.plugins.test.validation.ImplicitBean")));
-        assertTrue(service.getInjectableClassNames().stream().anyMatch(name -> name.equals("org.apache.logging.log4j.plugins.test.validation.ImplicitMethodBean")));
-        assertTrue(service.getInjectableClassNames().stream().anyMatch(name -> name.equals("org.apache.logging.log4j.plugins.test.validation.ProductionBean$Builder")));
-        assertTrue(service.getProducibleClassNames().stream().anyMatch(name -> name.equals("org.apache.logging.log4j.plugins.test.validation.ProductionBean")));
-        assertTrue(service.getDestructibleClassNames().stream().anyMatch(name -> name.equals("org.apache.logging.log4j.plugins.test.validation.ProductionBean")));
+        assertTrue(service.getInjectionBeans().containsKey("org.apache.logging.log4j.plugins.test.validation.ExampleBean"));
+        assertTrue(service.getInjectionBeans().containsKey("org.apache.logging.log4j.plugins.test.validation.ImplicitBean"));
+        assertTrue(service.getInjectionBeans().containsKey("org.apache.logging.log4j.plugins.test.validation.ImplicitMethodBean"));
+        assertTrue(service.getInjectionBeans().containsKey("org.apache.logging.log4j.plugins.test.validation.ProductionBean$Builder"));
+        assertTrue(service.getProducerBeans().containsKey("org.apache.logging.log4j.plugins.test.validation.ProductionBean"));
+        assertTrue(service.getDestructorBeans().contains("org.apache.logging.log4j.plugins.test.validation.ProductionBean"));
+        assertTrue(service.getPluginBeans().containsKey(FakePlugin.class.getName()));
     }
 }
\ No newline at end of file
diff --git a/log4j-plugins/src/test/java9/module-info.java b/log4j-plugins/src/test/java9/module-info.java
index 41a87f2..4195946 100644
--- a/log4j-plugins/src/test/java9/module-info.java
+++ b/log4j-plugins/src/test/java9/module-info.java
@@ -23,10 +23,14 @@ open module org.apache.logging.log4j.plugins {
     requires org.junit.platform.engine;
     requires junit;
 
-    provides org.apache.logging.log4j.plugins.processor.PluginService with org.apache.logging.log4j.plugins.convert.plugins.Log4jPlugins;
-    provides org.apache.logging.log4j.plugins.di.spi.BeanInfoService with org.apache.logging.log4j.plugins.convert.plugins.Log4jBeanInfo;
-    provides javax.annotation.processing.Processor with org.apache.logging.log4j.plugins.processor.PluginProcessor, org.apache.logging.log4j.plugins.processor.BeanProcessor;
+    provides org.apache.logging.log4j.plugins.processor.PluginService with
+            org.apache.logging.log4j.plugins.convert.plugins.Log4jPlugins;
+    provides org.apache.logging.log4j.plugins.di.spi.PluginModule with
+            org.apache.logging.log4j.plugins.convert.plugins.Log4jModule;
+    provides javax.annotation.processing.Processor with
+            org.apache.logging.log4j.plugins.processor.PluginProcessor,
+            org.apache.logging.log4j.plugins.processor.BeanProcessor;
 
     uses org.apache.logging.log4j.plugins.processor.PluginService;
-    uses org.apache.logging.log4j.plugins.di.spi.BeanInfoService;
+    uses org.apache.logging.log4j.plugins.di.spi.PluginModule;
 }
diff --git a/pom.xml b/pom.xml
index 3177d6b..5217a8f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
+
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one or more
   ~ contributor license agreements. See the NOTICE file distributed with
@@ -1099,7 +1100,6 @@
                 <version>${errorprone.version}</version>
               </path>
             </annotationProcessorPaths>
-            <forceJavacCompilerUse>true</forceJavacCompilerUse>
             <parameters>true</parameters>
           </configuration>
         </plugin>