
infra.beans.factory.support.DependencyInjector Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2017 - 2024 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see [https://www.gnu.org/licenses/]
*/
package infra.beans.factory.support;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Set;
import infra.beans.BeanUtils;
import infra.beans.TypeConverter;
import infra.beans.factory.config.AutowireCapableBeanFactory;
import infra.beans.factory.config.ConfigurableBeanFactory;
import infra.beans.factory.config.DependencyDescriptor;
import infra.core.MethodParameter;
import infra.lang.Nullable;
import infra.util.ExceptionUtils;
import infra.util.ObjectUtils;
import static infra.beans.factory.support.StandardBeanFactory.raiseNoMatchingBeanFound;
/**
* Dependency injector
*
* @author Harry Yang
* @since 4.0 2021/12/27 21:06
*/
public class DependencyInjector {
@Nullable
private DependencyResolvingStrategies resolvingStrategies;
@Nullable
private final AutowireCapableBeanFactory beanFactory;
public DependencyInjector(@Nullable AutowireCapableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
//---------------------------------------------------------------------
// Inject to target injection-point
//---------------------------------------------------------------------
public T inject(Constructor constructor, @Nullable Object... providedArgs) {
Object[] parameter = resolveArguments(constructor, providedArgs);
return BeanUtils.newInstance(constructor, parameter);
}
public Object inject(Method method, Object bean, @Nullable Object... providedArgs) {
Object[] args = resolveArguments(method, providedArgs);
try {
return method.invoke(bean, args);
}
catch (IllegalAccessException e) {
throw new IllegalStateException("Could not access method: " + method);
}
catch (InvocationTargetException e) {
throw ExceptionUtils.sneakyThrow(e.getTargetException());
}
}
//---------------------------------------------------------------------
// Resolving dependency
//---------------------------------------------------------------------
@Nullable
public Object[] resolveArguments(Executable executable, @Nullable Object... providedArgs) {
int parameterLength = executable.getParameterCount();
if (parameterLength != 0) {
Object[] arguments = new Object[parameterLength];
Parameter[] parameters = executable.getParameters();
for (int i = 0; i < arguments.length; i++) {
Object provided = findProvided(parameters[i], providedArgs);
if (provided == null) {
MethodParameter methodParam = MethodParameter.forExecutable(executable, i);
DependencyDescriptor descriptor = new DependencyDescriptor(methodParam, true);
Object resolved = resolve(descriptor, null, null, null, beanFactory);
if (resolved == null) {
if (beanFactory instanceof StandardBeanFactory sbf) {
if (sbf.isRequired(descriptor)) {
sbf.raiseNoMatchingBeanFound(descriptor.getDependencyType(), descriptor);
}
}
else if (descriptor.isRequired()) {
raiseNoMatchingBeanFound(descriptor);
}
}
arguments[i] = resolved;
}
else {
arguments[i] = provided;
}
}
return arguments;
}
return null;
}
@Nullable
public Object resolveValue(DependencyDescriptor descriptor) {
return resolveValue(descriptor, null, null, null);
}
@Nullable
public Object resolveValue(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) {
return resolve(descriptor, beanName, autowiredBeanNames, typeConverter, beanFactory);
}
@Nullable
Object resolve(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set autowiredBeanNames, @Nullable TypeConverter converter, @Nullable AutowireCapableBeanFactory beanFactory) {
if (beanFactory != null) {
return beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, converter);
}
else {
var context = new DependencyResolvingStrategy.Context(requestingBeanName, autowiredBeanNames, converter);
return getResolvingStrategies().resolveDependency(descriptor, context);
}
}
public DependencyResolvingStrategies getResolvingStrategies() {
DependencyResolvingStrategies strategies = this.resolvingStrategies;
if (strategies == null) {
strategies = new DependencyResolvingStrategies();
strategies.initStrategies(beanFactory instanceof ConfigurableBeanFactory cbf ? cbf.getBeanClassLoader() : null);
this.resolvingStrategies = strategies;
}
return strategies;
}
public void setResolvingStrategies(@Nullable DependencyResolvingStrategies resolvingStrategies) {
this.resolvingStrategies = resolvingStrategies;
}
@Nullable
public static Object findProvided(Parameter parameter, @Nullable Object[] providedArgs) {
if (ObjectUtils.isNotEmpty(providedArgs)) {
Class> dependencyType = parameter.getType();
for (final Object providedArg : providedArgs) {
if (dependencyType.isInstance(providedArg)) {
return providedArg;
}
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy