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 2022/07/23 23:40:38 UTC
[logging-log4j2] 01/02: Add more docs for plugins/DI
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 <ma...@apache.org>
AuthorDate: Sat Jul 23 18:00:27 2022 -0500
Add more docs for plugins/DI
Signed-off-by: Matt Sicker <ma...@apache.org>
---
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;