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 6caab9e27acaaa9600a0066f51ce1db514d30774 Author: Matt Sicker <[email protected]> AuthorDate: Sun Jun 20 16:28:55 2021 -0500 Clean up BeanManager API surface --- .../logging/log4j/core/config/di/BeanManager.java | 24 ++++ .../logging/log4j/core/config/di/Injector.java | 41 ------- .../log4j/core/config/di/ProviderFactory.java | 24 ---- .../core/config/di/impl/AbstractProducer.java | 3 +- .../core/config/di/impl/DefaultBeanManager.java | 122 ++++++++++----------- .../config/di/impl/DefaultInjectionTarget.java | 1 - .../di/impl/DefaultInjectionTargetFactory.java | 1 - .../impl/{DefaultInjector.java => Injector.java} | 10 +- .../log4j/core/config/di/impl/ProvidedBean.java | 9 +- .../log4j/core/config/di/impl/ProviderBean.java | 11 +- 10 files changed, 95 insertions(+), 151 deletions(-) diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/BeanManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/BeanManager.java index 967cc1f..4e35ae6 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/BeanManager.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/BeanManager.java @@ -28,6 +28,7 @@ import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.lang.reflect.Type; import java.util.ArrayList; @@ -50,6 +51,29 @@ public interface BeanManager extends AutoCloseable { Collection<Bean<?>> loadBeans(final Collection<Class<?>> beanClasses); /** + * Creates a bean for an injectable bean class. + */ + <T> Bean<T> createBean(final Class<T> beanClass); + + /** + * Creates a bean for a producer field. + * + * @param producerField field to obtain bean instance from + * @param owner owning bean for instance field or null for a static field + * @return newly created bean + */ + Bean<?> createBean(final Field producerField, final Bean<?> owner); + + /** + * Creates a bean for a producer method. + * + * @param producerMethod method to obtain bean instance from + * @param owner owning bean for instance method or null for a static method + * @return newly created bean + */ + Bean<?> createBean(final Method producerMethod, final Bean<?> owner); + + /** * Loads beans from the given classes. This looks for injectable classes and producers, registers them in this * manager, validates them, then returns the validated beans. * diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Injector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Injector.java deleted file mode 100644 index 52d74f0..0000000 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Injector.java +++ /dev/null @@ -1,41 +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.core.config.di; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Collection; - -public interface Injector { - <T> T construct(final Constructor<T> constructor, final Collection<InjectionPoint> points, - final InitializationContext<T> context); - - <D, T> T produce(final D producerInstance, final Method producerMethod, - final Collection<InjectionPoint> points, final InitializationContext<D> context); - - <T> void dispose(final T disposerInstance, final Method disposerMethod, - final Collection<InjectionPoint> points, final Object instance, - final InitializationContext<T> context); - - <T> void invoke(final T instance, final Method method, final Collection<InjectionPoint> points, - final InitializationContext<T> context); - - <D, T> void set(final D instance, final Field field, final InjectionPoint point, - final InitializationContext<D> context); -} diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ProviderFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ProviderFactory.java deleted file mode 100644 index 8981cbf..0000000 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ProviderFactory.java +++ /dev/null @@ -1,24 +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.core.config.di; - -import org.apache.logging.log4j.plugins.di.Provider; - -public interface ProviderFactory<T> { - Provider<T> getProvider(final InitializationContext<?> context); -} diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractProducer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractProducer.java index 710a396..06d09c1 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractProducer.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractProducer.java @@ -21,7 +21,6 @@ import org.apache.logging.log4j.core.config.di.Bean; import org.apache.logging.log4j.core.config.di.BeanManager; import org.apache.logging.log4j.core.config.di.InitializationContext; import org.apache.logging.log4j.core.config.di.InjectionPoint; -import org.apache.logging.log4j.core.config.di.Injector; import org.apache.logging.log4j.core.config.di.Producer; import java.lang.reflect.Method; @@ -43,7 +42,7 @@ abstract class AbstractProducer<P, T> implements Producer<T> { this.producerBean = producerBean; this.disposerMethod = disposerMethod; this.disposerInjectionPoints = Objects.requireNonNull(disposerInjectionPoints); - this.injector = new DefaultInjector(beanManager); + this.injector = new Injector(beanManager); } // context is managed separately as the declaring instance is only used for producing the object and is not a dependent of the bean diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultBeanManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultBeanManager.java index 75e4698..c13f16e 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultBeanManager.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultBeanManager.java @@ -25,7 +25,6 @@ import org.apache.logging.log4j.core.config.di.InitializationContext; import org.apache.logging.log4j.core.config.di.InjectionException; import org.apache.logging.log4j.core.config.di.InjectionPoint; import org.apache.logging.log4j.core.config.di.InjectionTargetFactory; -import org.apache.logging.log4j.core.config.di.Injector; import org.apache.logging.log4j.core.config.di.ProducerFactory; import org.apache.logging.log4j.core.config.di.ResolutionException; import org.apache.logging.log4j.core.config.di.ScopeContext; @@ -68,7 +67,7 @@ import java.util.stream.Stream; public class DefaultBeanManager implements BeanManager { - private final Injector injector = new DefaultInjector(this); + private final Injector injector = new Injector(this); private final Collection<Bean<?>> enabledBeans = ConcurrentHashMap.newKeySet(); private final Map<Type, Collection<Bean<?>>> beansByType = new ConcurrentHashMap<>(); @@ -83,29 +82,62 @@ public class DefaultBeanManager implements BeanManager { @Override public Collection<Bean<?>> loadBeans(final Collection<Class<?>> beanClasses) { - return beanClasses.stream() - .flatMap(beanClass -> loadBeans(beanClass).stream()) - .collect(Collectors.toSet()); + final Collection<Bean<?>> loadedBeans = new HashSet<>(); + for (final Class<?> beanClass : beanClasses) { + final Bean<?> bean = isInjectable(beanClass) ? createBean(beanClass) : null; + loadDisposerMethods(beanClass, bean); + for (final Method method : beanClass.getDeclaredMethods()) { + if (AnnotationUtil.isAnnotationPresent(method, Produces.class)) { + method.setAccessible(true); + loadedBeans.add(createBean(method, bean)); + } + } + for (final Field field : beanClass.getDeclaredFields()) { + if (AnnotationUtil.isAnnotationPresent(field, Produces.class)) { + field.setAccessible(true); + loadedBeans.add(createBean(field, bean)); + } + } + if (bean != null) { + loadedBeans.add(bean); + } + } + return loadedBeans; } - private <T> Collection<Bean<?>> loadBeans(final Class<T> beanClass) { - final Bean<T> created; - if (isInjectable(beanClass)) { - final Collection<Type> types = TypeUtil.getTypeClosure(beanClass); - final String name = AnnotatedElementNameProvider.getName(beanClass); - final Class<? extends Annotation> scopeType = getScopeType(beanClass); - final InjectionTargetFactory<T> factory = - new DefaultInjectionTargetFactory<>(this, injector, beanClass); - created = addBean(new InjectionTargetBean<>(types, name, scopeType, beanClass, factory)); - } else { - created = null; - } - loadDisposerMethods(beanClass, created); - final Collection<Bean<?>> beans = loadProducerBeans(beanClass, created); - if (created != null) { - beans.add(created); - } - return beans; + @Override + public <T> Bean<T> createBean(final Class<T> beanClass) { + final Collection<Type> types = TypeUtil.getTypeClosure(beanClass); + final String name = AnnotatedElementNameProvider.getName(beanClass); + final Class<? extends Annotation> scopeType = getScopeType(beanClass); + final InjectionTargetFactory<T> factory = + new DefaultInjectionTargetFactory<>(this, injector, beanClass); + return addBean(new InjectionTargetBean<>(types, name, scopeType, beanClass, factory)); + } + + @Override + public Bean<?> createBean(final Field producerField, final Bean<?> owner) { + final Collection<Type> types = TypeUtil.getTypeClosure(producerField.getGenericType()); + final String name = AnnotatedElementNameProvider.getName(producerField); + final Method disposerMethod = resolveDisposerMethod(types, name, owner); + final Collection<InjectionPoint> disposerIPs = + disposerMethod == null ? Set.of() : createExecutableInjectionPoints(disposerMethod, owner); + final ProducerFactory factory = + new FieldProducerFactory(this, owner, producerField, disposerMethod, disposerIPs); + return addBean(new ProducerBean<>(types, name, getScopeType(producerField), producerField.getDeclaringClass(), factory)); + } + + @Override + public Bean<?> createBean(final Method producerMethod, final Bean<?> owner) { + final Collection<Type> types = TypeUtil.getTypeClosure(producerMethod.getGenericReturnType()); + final String name = AnnotatedElementNameProvider.getName(producerMethod); + final Method disposerMethod = resolveDisposerMethod(types, name, owner); + final Collection<InjectionPoint> disposerIPs = + disposerMethod == null ? Collections.emptySet() : createExecutableInjectionPoints(disposerMethod, owner); + final Collection<InjectionPoint> producerIPs = createExecutableInjectionPoints(producerMethod, owner); + final ProducerFactory factory = + new MethodProducerFactory(this, owner, producerMethod, producerIPs, disposerMethod, disposerIPs); + return addBean(new ProducerBean<>(types, name, getScopeType(producerMethod), producerMethod.getDeclaringClass(), factory)); } private <T> Bean<T> addBean(final Bean<T> bean) { @@ -134,8 +166,8 @@ public class DefaultBeanManager implements BeanManager { beansByType.computeIfAbsent(type, ignored -> ConcurrentHashMap.newKeySet()).add(bean); } - private void loadDisposerMethods(final Class<?> metaClass, final Bean<?> bean) { - for (final Method method : metaClass.getDeclaredMethods()) { + private void loadDisposerMethods(final Class<?> beanClass, final Bean<?> bean) { + for (final Method method : beanClass.getDeclaredMethods()) { for (final Parameter parameter : method.getParameters()) { if (AnnotationUtil.isAnnotationPresent(parameter, Disposes.class)) { final String name = AnnotatedElementNameProvider.getName(parameter); @@ -147,46 +179,6 @@ public class DefaultBeanManager implements BeanManager { } } - private <P> Collection<Bean<?>> loadProducerBeans(final Class<P> producingClass, final Bean<P> producingBean) { - final Collection<Bean<?>> beans = new HashSet<>(); - for (final Method method : producingClass.getDeclaredMethods()) { - if (AnnotationUtil.isAnnotationPresent(method, Produces.class)) { - method.setAccessible(true); - beans.add(loadProducerBean(method, producingBean)); - } - } - for (final Field field : producingClass.getDeclaredFields()) { - if (AnnotationUtil.isAnnotationPresent(field, Produces.class)) { - field.setAccessible(true); - beans.add(loadProducerBean(field, producingBean)); - } - } - return beans; - } - - private Bean<?> loadProducerBean(final Method method, final Bean<?> producingBean) { - final Collection<Type> types = TypeUtil.getTypeClosure(method.getGenericReturnType()); - final String name = AnnotatedElementNameProvider.getName(method); - final Method disposerMethod = resolveDisposerMethod(types, name, producingBean); - final Collection<InjectionPoint> disposerIPs = disposerMethod == null ? Collections.emptySet() : - createExecutableInjectionPoints(disposerMethod, producingBean); - final Collection<InjectionPoint> producerIPs = createExecutableInjectionPoints(method, producingBean); - final ProducerFactory factory = new MethodProducerFactory( - this, producingBean, method, producerIPs, disposerMethod, disposerIPs); - return addBean(new ProducerBean<>(types, name, getScopeType(method), method.getDeclaringClass(), factory)); - } - - private Bean<?> loadProducerBean(final Field field, final Bean<?> producingBean) { - final Collection<Type> types = TypeUtil.getTypeClosure(field.getGenericType()); - final String name = AnnotatedElementNameProvider.getName(field); - final Method disposerMethod = resolveDisposerMethod(types, name, producingBean); - final Collection<InjectionPoint> disposerIPs = disposerMethod == null ? Collections.emptySet() : - createExecutableInjectionPoints(disposerMethod, producingBean); - final ProducerFactory factory = new FieldProducerFactory( - this, producingBean, field, disposerMethod, disposerIPs); - return addBean(new ProducerBean<>(types, name, getScopeType(field), field.getDeclaringClass(), factory)); - } - private Method resolveDisposerMethod(final Collection<Type> types, final String name, final Bean<?> disposingBean) { final List<Method> methods = disposesMethods.stream() .filter(method -> method.matches(types, name, disposingBean)) diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTarget.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTarget.java index 7807599..a6ebed9 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTarget.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTarget.java @@ -21,7 +21,6 @@ import org.apache.logging.log4j.core.config.di.InitializationContext; import org.apache.logging.log4j.core.config.di.InitializationException; import org.apache.logging.log4j.core.config.di.InjectionPoint; import org.apache.logging.log4j.core.config.di.InjectionTarget; -import org.apache.logging.log4j.core.config.di.Injector; import org.apache.logging.log4j.plugins.di.Disposes; import org.apache.logging.log4j.plugins.di.Inject; import org.apache.logging.log4j.plugins.di.Produces; diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTargetFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTargetFactory.java index 3193c36..f321cc1 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTargetFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTargetFactory.java @@ -23,7 +23,6 @@ import org.apache.logging.log4j.core.config.di.DefinitionException; import org.apache.logging.log4j.core.config.di.InjectionPoint; import org.apache.logging.log4j.core.config.di.InjectionTarget; import org.apache.logging.log4j.core.config.di.InjectionTargetFactory; -import org.apache.logging.log4j.core.config.di.Injector; import org.apache.logging.log4j.plugins.di.Inject; import org.apache.logging.log4j.plugins.di.PostConstruct; import org.apache.logging.log4j.plugins.di.PreDestroy; diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/Injector.java similarity index 96% rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjector.java rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/Injector.java index 3e9bb94..e29b6ad 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjector.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/Injector.java @@ -21,7 +21,6 @@ import org.apache.logging.log4j.core.config.di.BeanManager; import org.apache.logging.log4j.core.config.di.InitializationContext; import org.apache.logging.log4j.core.config.di.InitializationException; import org.apache.logging.log4j.core.config.di.InjectionPoint; -import org.apache.logging.log4j.core.config.di.Injector; import org.apache.logging.log4j.plugins.di.Disposes; import org.apache.logging.log4j.plugins.util.AnnotationUtil; import org.apache.logging.log4j.plugins.util.TypeUtil; @@ -34,14 +33,13 @@ import java.lang.reflect.Parameter; import java.util.Collection; import java.util.Optional; -public class DefaultInjector implements Injector { +public class Injector { private final BeanManager beanManager; - public DefaultInjector(final BeanManager beanManager) { + public Injector(final BeanManager beanManager) { this.beanManager = beanManager; } - @Override public <T> T construct(final Constructor<T> constructor, final Collection<InjectionPoint> points, final InitializationContext<T> context) { try { return constructor.newInstance(createArguments(constructor.getParameters(), points, context, null)); @@ -52,7 +50,6 @@ public class DefaultInjector implements Injector { } } - @Override public <D, T> T produce(final D producerInstance, final Method producerMethod, final Collection<InjectionPoint> points, final InitializationContext<D> context) { try { return TypeUtil.cast(producerMethod.invoke(producerInstance, createArguments(producerMethod.getParameters(), points, context, null))); @@ -63,7 +60,6 @@ public class DefaultInjector implements Injector { } } - @Override public <T> void dispose(final T disposerInstance, final Method disposerMethod, final Collection<InjectionPoint> points, final Object instance, final InitializationContext<T> context) { try { disposerMethod.invoke(disposerInstance, createArguments(disposerMethod.getParameters(), points, context, instance)); @@ -74,7 +70,6 @@ public class DefaultInjector implements Injector { } } - @Override public <T> void invoke(final T instance, final Method method, final Collection<InjectionPoint> points, final InitializationContext<T> context) { try { method.invoke(instance, createArguments(method.getParameters(), points, context, null)); @@ -85,7 +80,6 @@ public class DefaultInjector implements Injector { } } - @Override public <D, T> void set(final D instance, final Field field, final InjectionPoint point, final InitializationContext<D> context) { final Optional<T> optionalValue = beanManager.getInjectableValue(point, context); optionalValue.ifPresent(value -> { diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProvidedBean.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProvidedBean.java index 655b8c0..393ce42 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProvidedBean.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProvidedBean.java @@ -20,20 +20,21 @@ package org.apache.logging.log4j.core.config.di.impl; import org.apache.logging.log4j.core.config.di.Bean; import org.apache.logging.log4j.core.config.di.InitializationContext; import org.apache.logging.log4j.core.config.di.InjectionPoint; -import org.apache.logging.log4j.core.config.di.ProviderFactory; import org.apache.logging.log4j.plugins.di.Provider; import org.apache.logging.log4j.plugins.util.TypeUtil; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Collection; +import java.util.function.Function; class ProvidedBean<T> implements Bean<T> { private final Collection<Type> types; private final Bean<Provider<T>> providerBean; - private final ProviderFactory<T> providerFactory; + private final Function<InitializationContext<?>, Provider<T>> providerFactory; - ProvidedBean(final Type type, final Bean<Provider<T>> providerBean, final ProviderFactory<T> providerFactory) { + ProvidedBean(final Type type, final Bean<Provider<T>> providerBean, + final Function<InitializationContext<?>, Provider<T>> providerFactory) { this.types = TypeUtil.getTypeClosure(type); this.providerBean = providerBean; this.providerFactory = providerFactory; @@ -41,7 +42,7 @@ class ProvidedBean<T> implements Bean<T> { @Override public T create(final InitializationContext<T> context) { - return providerFactory.getProvider(context).get(); + return providerFactory.apply(context).get(); } @Override diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProviderBean.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProviderBean.java index 5b00f50..138b9f9 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProviderBean.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProviderBean.java @@ -20,28 +20,29 @@ package org.apache.logging.log4j.core.config.di.impl; import org.apache.logging.log4j.core.config.di.Bean; import org.apache.logging.log4j.core.config.di.InitializationContext; import org.apache.logging.log4j.core.config.di.InjectionPoint; -import org.apache.logging.log4j.core.config.di.ProviderFactory; import org.apache.logging.log4j.plugins.di.Provider; import org.apache.logging.log4j.plugins.util.TypeUtil; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Collection; +import java.util.function.Function; class ProviderBean<T> implements Bean<Provider<T>> { private final Collection<Type> types; private final Bean<T> bean; - private final ProviderFactory<T> factory; + private final Function<InitializationContext<?>, Provider<T>> providerFactory; - ProviderBean(final Type providerType, final Bean<T> bean, final ProviderFactory<T> factory) { + ProviderBean(final Type providerType, final Bean<T> bean, + final Function<InitializationContext<?>, Provider<T>> providerFactory) { this.types = TypeUtil.getTypeClosure(providerType); this.bean = bean; - this.factory = factory; + this.providerFactory = providerFactory; } @Override public Provider<T> create(final InitializationContext<Provider<T>> context) { - return factory.getProvider(context); + return providerFactory.apply(context); } @Override
