This is an automated email from the ASF dual-hosted git repository. mattsicker pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit f92a61242211ab496e9542bbbb9d1681ef0a9d9d Author: Matt Sicker <[email protected]> AuthorDate: Sat Jul 23 18:00:27 2022 -0500 Add more docs for plugins/DI Signed-off-by: Matt Sicker <[email protected]> --- log4j-plugins/src/main/java/module-info.java | 8 +++-- .../logging/log4j/plugins/di/DefaultInjector.java | 5 ++- .../apache/logging/log4j/plugins/di/Injector.java | 40 ++++++++++++++++++---- .../org/apache/logging/log4j/plugins/di/Key.java | 15 +++++++- 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/log4j-plugins/src/main/java/module-info.java b/log4j-plugins/src/main/java/module-info.java index b884b96944..96e35e9476 100644 --- a/log4j-plugins/src/main/java/module-info.java +++ b/log4j-plugins/src/main/java/module-info.java @@ -16,12 +16,16 @@ */ /** - * Log4j plugin annotations and dependency injection system. + * Log4j plugin annotations and dependency injection system. Plugins encompass a variety of customizable + * Log4j interfaces and classes that are addressable by {@linkplain org.apache.logging.log4j.plugins.Named name} or type + * including {@linkplain org.apache.logging.log4j.plugins.Configurable configurable plugins} which are created from a + * parsed tree of {@linkplain org.apache.logging.log4j.plugins.Node configuration nodes} along with other + * {@linkplain org.apache.logging.log4j.plugins.Namespace namespaces} for different dependency injection purposes. * * @see org.apache.logging.log4j.plugins.Inject * @see org.apache.logging.log4j.plugins.Plugin * @see org.apache.logging.log4j.plugins.PluginFactory - * @see org.apache.logging.log4j.plugins.Namespace + * @see org.apache.logging.log4j.plugins.di.Injector */ module org.apache.logging.log4j.plugins { exports org.apache.logging.log4j.plugins; diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java index aee5cf183c..cfb5d19964 100644 --- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java +++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java @@ -67,7 +67,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.ServiceLoader; import java.util.Set; import java.util.UnknownFormatConversionException; import java.util.concurrent.ConcurrentHashMap; @@ -713,12 +712,12 @@ class DefaultInjector implements Injector { private Scope getScopeForMethod(final Method method) { final Annotation methodScope = AnnotationUtil.getMetaAnnotation(method, ScopeType.class); - return methodScope != null ? scopes.get(methodScope.annotationType()) : getScopeForType(method.getReturnType()); + return methodScope != null ? getScope(methodScope.annotationType()) : getScopeForType(method.getReturnType()); } private Scope getScopeForType(final Class<?> type) { final Annotation scope = AnnotationUtil.getMetaAnnotation(type, ScopeType.class); - return scope != null ? scopes.get(scope.annotationType()) : DefaultScope.INSTANCE; + return scope != null ? getScope(scope.annotationType()) : DefaultScope.INSTANCE; } private static boolean isCompatibleValidator( diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java index a35440b87d..c9b01a5aa2 100644 --- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java +++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java @@ -17,6 +17,7 @@ package org.apache.logging.log4j.plugins.di; +import org.apache.logging.log4j.plugins.Configurable; import org.apache.logging.log4j.plugins.FactoryType; import org.apache.logging.log4j.plugins.Node; import org.apache.logging.log4j.plugins.convert.TypeConverter; @@ -26,16 +27,35 @@ import java.lang.reflect.Type; import java.util.function.Supplier; /** - * Central interface for dependency injection operations. An Injector maintains a registry of bindings between {@link Key}s to - * {@link Supplier}s along with a registry of {@link Scope}s for different scope annotation types. Injectors may be - * {@linkplain #init() initialized} with {@link InjectorCallback} services. + * Manages dependency injection of a set of bindings between {@link Key}s and {@link Supplier}s lifecycle-bound to + * {@link Scope}s. Keys describe the type, name, namespace, qualifier type, and order of a binding. Suppliers are known + * as <i>factories</i>, and factories may have injectable dependencies on other bindings upon creation. Scopes control + * the lifecycle of instances returned by a binding's factory. + * + * <p>When first creating an Injector, invocation of {@link #init()} will invoke all registered {@link InjectorCallback} + * services in {@linkplain InjectorCallback#getOrder() numeric order}. These callbacks may register bindings + * {@linkplain #registerBinding(Key, Supplier) programmatically} or via {@linkplain #registerBundle(Object) bundle classes}, + * and set a {@linkplain #setReflectionAccessor(ReflectionAccessor) default reflection accessor} for customizing the + * context in which private reflection operations are performed. Additional scopes + * {@linkplain #registerScope(Class, Scope) may also be registered}.</p> + * + * <p>Factories for keys can be looked up {@linkplain #getFactory(Key) by key} or {@linkplain #getFactory(Class) by class}. + * Any object created outside this system can have {@linkplain #injectMembers(Object) its members injected}.</p> + * + * <p>A parsed {@linkplain Node configuration node} can be {@linkplain #configure(Node) configured} using its referenced + * plugin class to return the plugin instance. Configuring a node configures its children nodes and consumes its + * attributes before returning the plugin instance.</p> */ public interface Injector { + /** + * The key corresponding to the current Injector. + */ Key<Injector> KEY = new Key<>() {}; /** * Initializes this Injector with all registered {@link InjectorCallback} services in - * {@linkplain InjectorCallback#getOrder() integral order}. + * {@linkplain InjectorCallback#getOrder() integral order}. This method should only be invoked after construction + * of a fresh Injector. */ void init(); @@ -107,7 +127,13 @@ public interface Injector { void injectMembers(final Object instance); /** - * Creates a plugin instance using the provided configuration node. + * Creates a plugin instance using the provided configuration node. Unless the plugin + * {@linkplain Configurable#deferChildren() defers children nodes}, child nodes are configured first before + * configuring this node. Each node's plugin should consume all supported + * {@linkplain org.apache.logging.log4j.plugins.PluginAttribute attributes} through dependency injection along with + * any other instances that can be provided through + * {@linkplain org.apache.logging.log4j.plugins.visit.NodeVisitor node visitor strategies} or general bindings from + * {@link #getFactory(Key)}. The end result of {@link Node#getObject()} is returned for convenience. * * @param node configuration node containing a plugin type, attributes, and child nodes to consume for dependency injection * @param <T> type of instance the given node configures @@ -133,7 +159,9 @@ public interface Injector { /** * Registers a bundle into this Injector. A bundle is an instance of a class with methods annotated with - * {@link FactoryType}-annotated annotations which provide dependency-injected bindings. + * {@link FactoryType}-annotated annotations which provide dependency-injected bindings. Bindings registered + * via bundles are merged with the existing bindings in this Injector based on the {@linkplain Key#getOrder() order} + * of the methods to determine ambiguities. * * @param bundle bundle to install with factory methods for factories */ diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java index b85658af16..4cd1156465 100644 --- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java +++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java @@ -86,25 +86,38 @@ public class Key<T> { hashCode = Objects.hash(type, qualifierType, name.toLowerCase(Locale.ROOT), namespace.toLowerCase(Locale.ROOT)); } + /** + * Returns the generic type of this key. + */ public final Type getType() { return type; } + /** + * Returns the raw type of this key corresponding to its generic type. + */ public final Class<T> getRawType() { return rawType; } + /** + * Returns the name of this key. Names are case-insensitive. If this key has no defined name, then this returns + * an empty string. + */ public final String getName() { return name; } + /** + * Returns the namespace of this key. If this key has no defined namespace, then this returns an empty string. + */ public final String getNamespace() { return namespace; } /** * Returns the ordinal value of this key. Keys that are otherwise equal can be compared by this - * ordinal using the natural integer comparator. + * ordinal using the natural integer comparator where ties should default to keeping an existing binding intact. */ public final int getOrder() { return order;
