////
    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.
////
= Dependency Injection
Matt Sicker <mattsicker@apache.org>

++++
<link rel="stylesheet" type="text/css" href="../css/tables.css">
++++

Log4j 3.x uses a more sophisticated dependency injection API inspired by https://javaee.github.io/javaee-spec/javadocs/javax/inject/package-summary.html[`javax.inject`] and its open source implementations such as https://github.com/zsoltherpai/feather[Feather] and https://github.com/google/guice[Guice].
Dependency injection can be thought of as a replacement for calling `new` or custom factory methods in Java code; alternatively, it can be thought of as a factory for factory instances.
Classes define _injection points_ which may be fields, method parameters, and constructor parameters, whose values are injected at runtime.
Classes may define _factory methods_ which provide a way to create instances of their return type while allowing for dependency injection of the factory method's arguments.
Injector callback services may be registered for customizing the dependency injection system at initialization.

== Overview

The `org.apache.logging.log4j.plugins.di.Injector` runtime keeps a registry of bindings between `Key<T>` and `Supplier<T>`, where `org.apache.logging.log4j.plugins.di.Key<T>` describes an instance type `T`, optional qualifier annotation type, and optional name plus namespace, and  `java.util.function.Supplier<T>` defines a factory for obtaining instances of `T` matching the corresponding `Key<T>`.
To obtain a factory for a given key, if a binding is not already registered for said key, then the raw class of the key (i.e., the `Class<T>` instance from `Key<T>`) is checked for a single constructor annotated with `@org.apache.logging.log4j.plugins.Inject` or a no-arg constructor if no `@Inject` constructor is present.
The injectable constructor is invoked with arguments which are obtained by looking up factories matching the `Key<?>` of each constructor parameter.
Then, fields that are annotated with `@Inject` or annotated with an annotation that is itself annotated with `@QualifierType` (i.e., a _qualifier annotation_) are injected from factories matching the `Key<?>` of the field.
Next, methods that are annotated with `@Inject` or have a parameter annotated with a qualifier annotation are invoked using factories matching the `Key<?>` of each parameter.
Finally, no-arg methods annotated with `@Inject` are invoked which can be useful for post-injection initialization logic.

Bindings may be registered using `Injector::registerBinding` or `Injector::registerBindingIfAbsent` using explicit `Key<T>` instances, or they may be registered using `Injector::registerBundle` as _bundles_ which are instances or injectable `Class<T>` instances that contain one or more annotated factory methods.
Annotated factory methods are non-abstract methods annotated with an annotation that is itself annotated with `@org.apache.logging.log4j.plugins.FactoryType`.
Built-in factory annotations include `@org.apache.logging.log4j.plugins.Factory` and `@org.apache.logging.log4j.plugins.PluginFactory`.

`Injector` can create `@Configurable` namespace plugins from a tree of `org.apache.logging.log4j.plugins.Node` instances using `Injector::configure`.
This allows for node attributes and child nodes to be injected into a plugin class along with any other registered bindings.
To configure a `Node`, its plugin class is checked for a static method annotated with a factory annotation (such as `@PluginFactory` or `@Factory`) first before falling back to checking for an `@Inject` constructor or a no-args constructor.
This static factory method or constructor has its parameters injected.
If the return value of a static plugin factory method implements `java.util.function.Supplier`, then member injection is performed on the instance and the return value of `Supplier::get` is returned instead.
See link:./plugins.html[Plugins] for more information.

`Injector` can inject members into an arbitrary object instance by using `Injector::injectMembers`.
This can be useful for injecting Log4j-managed instances into external or application code.
An `Injector` can be obtained via `LoggerContext::getInjector`.

=== Injection Points

Injection points are injectable fields or parameters where a dependency should be injected.
_Injectable fields_ are fields annotated with `@Inject` or a qualifier annotation.
_Injectable methods_ are methods annotated with `@Inject` or are not annotated with a factory annotation and have at least one parameter annotated with a qualifier annotation.
_Injectable constructors_ are constructors annotated with `@Inject`; only one such constructor should exist per class.
When a field or parameter is annotated with a name-providing annotation (i.e., an annotation annotated with `@org.apache.logging.log4j.plugins.name.NameProvider`), then the provided name or name of the field or parameter are included in the `Key<T>` for the injection point.
When these elements are annotated with a `@Namespace` annotation or meta-annotation, then that namespace name is included in the `Key<T>` for the injection point.
Similarly, when a field or parameter is annotated with a qualifier annotation, then that qualifier annotation type is included in the `Key<T>` for the injection point.

An example of each injection point with a no-arg `@Inject` method to show the post-injected state:

[source,java]
----
class ExampleBean {
    @Override
    public String toString() {
        return "ExampleBean";
    }
}

class FieldInjection {
    @Inject
    ExampleBean exampleBean;

    @Inject
    void init() {
        System.out.println(exampleBean);
    }
}

class ConstructorInjection {
    final ExampleBean bean;

    @Inject
    ConstructorInjection(final ExampleBean exampleBean) {
        bean = exampleBean;
    }

    @Inject
    void init() {
        System.out.println(exampleBean);
    }
}

class MethodInjection {
    ExampleBean bean;

    @Inject
    void setBean(final ExampleBean exampleBean) {
        bean = exampleBean;
    }

    @Inject
    void init() {
        System.out.println(exampleBean);
    }
}
----

=== Names and Qualifiers

Qualifiers are annotations that are annotated with `@org.apache.logging.log4j.plugins.QualifierType`.
Qualifiers provide a way to match dependencies and factories based on more than just their type.
For example, the `@org.apache.logging.log4j.plugins.Named` qualifier allows for creating different bindings of the same type with different names (along with support for aliases).
Qualifiers on an injection point request a binding with that qualifier type and name.
Qualifiers on a factory method register a binding with that qualifier type and name.
The name for a qualifier is provided via an `org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider` strategy class given in the `@NameProvider` annotation declared on the qualifier annotation.
Aliases are likewise provided via an `org.apache.logging.log4j.plugins.name.AnnotatedElementAliasesProvider` strategy class given in the `@AliasesProvider` annotated declared on the qualifier annotation.

=== Scopes

Scopes control the lifecycle of instances returned from a factory.
Scopes correspond to an annotation that is annotated with `@org.apache.logging.log4j.plugins.ScopeType`.
By default, `@org.apache.logging.log4j.plugins.Singleton` and the default scope are supported.
The `@Singleton` scope ensures that only a single instance is returned from factories bound in that scope.
The default scope returns a new instance every time.
Additional scopes may be registered via `Injector::registerScope`.

== Injector Callbacks

An `Injector` may be initialized with `org.apache.logging.log4j.plugins.di.InjectorCallback` service classes.
These service classes must be declared in their respective `module-info.java` files containing `provides org.apache.logging.log4j.plugins.di.InjectorCallback with my.fully.qualified.ClassName;` and should also be declared in a file named `META-INF/services/org.apache.logging.log4j.plugins.di.InjectorCallback` containing the line `my.fully.qualified.ClassName` for traditional classpath usage.
Callback services are invoked in the order defined by each `InjectorCallback::getOrder` value in the natural integer order (from `Integer.MIN_VALUE` to `Integer.MAX_VALUE`).
Each callback is given the `Injector` that invoked `Injector::init` where it can be introspected and modified.
Log4j includes one such callback with an order value of 0 which supports registering callbacks that invoke before or after this default.
This default callback registers default bindings for various keys if none are already registered.

=== Configurable Bindings

The default callback sets up bindings for the following keys if none have been registered.
Some of these bindings were previously configured through various system properties which are supported via the default callback and its default bindings, though they can be directly registered via custom callbacks with a negative order value.

* `org.apache.logging.log4j.core.ContextDataInjector`
* `org.apache.logging.log4j.core.config.ConfigurationFactory`
* `org.apache.logging.log4j.core.config.composite.MergeStrategy`
* `org.apache.logging.log4j.core.impl.LogEventFactory`
* `org.apache.logging.log4j.core.lookup.InterpolatorFactory`
* `org.apache.logging.log4j.core.lookup.StrSubstitutor`
* `org.apache.logging.log4j.core.selector.ContextSelector`
* `org.apache.logging.log4j.core.time.Clock`
* `org.apache.logging.log4j.core.time.NanoClock`
* `org.apache.logging.log4j.core.util.ShutdownCallbackRegistry`
* `org.apache.logging.log4j.core.util.WatchManager`
* `org.apache.logging.log4j.core.config.ConfigurationScheduler`
