io.micronaut.spring.context.factory.MicronautBeanFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of micronaut-spring-context Show documentation
Show all versions of micronaut-spring-context Show documentation
Extensions to integrate Micronaut and Spring
The newest version!
/*
* Copyright 2017-2020 original authors
*
* Licensed 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
*
* https://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 io.micronaut.spring.context.factory;
import io.micronaut.context.BeanContext;
import io.micronaut.context.BeanRegistration;
import io.micronaut.context.RuntimeBeanDefinition;
import io.micronaut.context.annotation.*;
import io.micronaut.context.exceptions.NoSuchBeanException;
import io.micronaut.core.annotation.AnnotationMetadata;
import io.micronaut.core.annotation.AnnotationUtil;
import io.micronaut.core.annotation.Internal;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.naming.NameResolver;
import io.micronaut.core.reflect.InstantiationUtils;
import io.micronaut.core.util.ArgumentUtils;
import io.micronaut.core.util.ArrayUtils;
import io.micronaut.core.util.StringUtils;
import io.micronaut.inject.BeanDefinition;
import io.micronaut.inject.BeanDefinitionReference;
import io.micronaut.inject.DisposableBeanDefinition;
import io.micronaut.inject.InstantiatableBeanDefinition;
import io.micronaut.inject.ParametrizedInstantiatableBeanDefinition;
import io.micronaut.inject.qualifiers.Qualifiers;
import io.micronaut.spring.beans.MicronautContextInternal;
import io.micronaut.spring.context.aware.SpringAwareListener;
import jakarta.inject.Singleton;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.AbstractBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.Role;
import org.springframework.core.OrderComparator;
import org.springframework.core.ResolvableType;
import org.springframework.stereotype.Component;
import org.springframework.util.ConcurrentReferenceHashMap;
import java.io.Closeable;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Stream;
/**
* Implementation of the {@link ListableBeanFactory} interface for Micronaut.
*
* @author graemerocher
* @since 1.0
*/
@Singleton
@Internal
public class MicronautBeanFactory extends DefaultListableBeanFactory implements ListableBeanFactory, AutowireCapableBeanFactory, HierarchicalBeanFactory, ConfigurableListableBeanFactory, MicronautContextInternal {
private final BeanContext beanContext;
private final Map> beanDefinitionMap = new LinkedHashMap<>(200);
// only used for by name lookups
private final Map> beanDefinitionsByName = new LinkedHashMap<>(200);
private final SpringAwareListener springAwareListener;
private final Map>> beanTypeCache = new ConcurrentReferenceHashMap<>();
private final Map beanNamesForTypeCache = new ConcurrentReferenceHashMap<>();
private final MicronautBeanFactoryConfiguration configuration;
private final List> beanExcludes;
/**
* The default constructor.
* @param beanContext The target Micronaut context
* @param awareListener The spring aware listener
* @param configuration Configuration
*/
public MicronautBeanFactory(
BeanContext beanContext,
SpringAwareListener awareListener,
MicronautBeanFactoryConfiguration configuration) {
this.beanContext = beanContext;
this.springAwareListener = awareListener;
this.configuration = configuration;
this.beanExcludes = configuration.getBeanExcludes();
final Collection> references = beanContext.getBeanDefinitionReferences();
for (BeanDefinitionReference> reference : references) {
final BeanDefinition> definition = reference.load(beanContext);
if (definition instanceof ParametrizedInstantiatableBeanDefinition || (!(definition instanceof InstantiatableBeanDefinition))) {
// Spring doesn't have a similar concept. Consider these internal / non-public beans.
continue;
}
if (beanExcludes.contains(definition.getBeanType())) {
continue;
}
if (definition.isEnabled(beanContext)) {
if (definition.isIterable()) {
Collection extends BeanDefinition>> beanDefinitions = beanContext.getBeanDefinitions(definition.getBeanType());
for (BeanDefinition> beanDefinition : beanDefinitions) {
String beanName = computeBeanName(beanDefinition);
beanDefinitionMap.put(beanName, beanDefinition);
}
} else {
String beanName = computeBeanName(definition);
beanDefinitionMap.put(beanName, definition);
}
// handle component differently so that the value is a unique bean name
if (definition.isAnnotationPresent(Component.class)) {
// explicit handling of named beans
final Optional v = definition.getValue(Component.class, String.class);
v.ifPresent(s -> beanDefinitionsByName.put(s, definition));
}
// handle Spring's @Bean differently so that the value is a unique bean name
if (definition.isAnnotationPresent(org.springframework.context.annotation.Bean.class)) {
// explicit handling of named beans
final Optional v = definition.getValue(org.springframework.context.annotation.Bean.class, String.class);
v.ifPresent(s -> beanDefinitionsByName.put(s, definition));
}
}
}
}
/**
* Shared logic for Micronaut singleton rules.
* @param annotationMetadata The metadata
* @return True if is singleton
*/
public static boolean isSingleton(AnnotationMetadata annotationMetadata) {
if (annotationMetadata.hasDeclaredStereotype(org.springframework.context.annotation.Bean.class)) {
final String scope = annotationMetadata.stringValue(org.springframework.context.annotation.Scope.class).orElse(null);
return scope == null || "singleton".equalsIgnoreCase(scope);
}
if (annotationMetadata.hasDeclaredStereotype(AnnotationUtil.SINGLETON)) {
return true;
} else {
if (!annotationMetadata.hasDeclaredStereotype(AnnotationUtil.SCOPE) &&
annotationMetadata.hasDeclaredStereotype(DefaultScope.class)) {
return annotationMetadata.stringValue(DefaultScope.class)
.map(t -> t.equals(Singleton.class.getName()) || t.equals(AnnotationUtil.SINGLETON))
.orElse(false);
} else {
return false;
}
}
}
private String computeBeanName(BeanDefinition> definition) {
String name;
if (definition instanceof NameResolver) {
name = ((NameResolver) definition).resolveName().orElse(Primary.class.getSimpleName());
} else {
name = definition.getValue(AnnotationUtil.NAMED, String.class).orElseGet(() ->
definition.getAnnotationTypeByStereotype(AnnotationUtil.QUALIFIER).map(Class::getSimpleName).orElse(definition.getClass().getSimpleName())
);
}
return definition.getBeanType().getName() + "(" + name + ")";
}
@Override
public @NonNull
Object getBean(@NonNull String name) throws BeansException {
if (super.isAlias(name)) {
final String[] aliases = super.getAliases(name);
for (String alias : aliases) {
if (containsBean(alias)) {
return getBean(alias);
}
}
}
if (super.containsSingleton(name)) {
final Object singleton = super.getSingleton(name, true);
if (singleton == null) {
throw new NoSuchBeanDefinitionException(name);
}
return singleton;
} else {
Class> type = getType(name);
BeanDefinition> definition;
if (type != null) {
definition = beanDefinitionMap.get(name);
} else {
definition = beanDefinitionsByName.get(name);
if (definition != null) {
type = definition.getBeanType();
}
}
if (definition != null && type != null) {
return beanContext.getBean(definition);
}
throw new NoSuchBeanDefinitionException(name);
}
}
@Override
public @NonNull
T getBean(@NonNull String name, @NonNull Class requiredType) throws BeansException {
ArgumentUtils.requireNonNull("requiredType", requiredType);
if (beanExcludes.contains(requiredType)) {
throw new NoSuchBeanDefinitionException(requiredType);
}
try {
if (containsBeanDefinition(name)) {
@SuppressWarnings("unchecked")
BeanDefinition beanDefinition = (BeanDefinition) beanDefinitionMap.get(name);
if (requiredType.isAssignableFrom(requiredType)) {
return beanContext.getBean(beanDefinition);
}
}
if (isAlias(name)) {
final String[] aliases = getAliases(name);
for (String alias : aliases) {
if (super.containsSingleton(alias)) {
return super.getBean(alias, requiredType);
}
}
}
if (super.containsSingleton(name)) {
final Object o = super.getBean(name);
if (requiredType.isInstance(o)) {
return (T) o;
}
}
return beanContext.getBean(requiredType, Qualifiers.byName(name));
} catch (NoSuchBeanException e) {
throw new NoSuchBeanDefinitionException(requiredType, e.getMessage());
} catch (Exception e) {
throw new BeanCreationException(name, e.getMessage(), e);
}
}
@Override
public @NonNull
Object getBean(@NonNull String name, @NonNull Object... args) throws BeansException {
final Class> type = getType(name);
if (type != null) {
return beanContext.createBean(type, args);
}
throw new NoSuchBeanDefinitionException(name);
}
@Override
public @NonNull
T getBean(@NonNull Class requiredType) throws BeansException {
ArgumentUtils.requireNonNull("requiredType", requiredType);
if (beanExcludes.contains(requiredType)) {
throw new NoSuchBeanDefinitionException(requiredType);
}
// unfortunate hack
try {
final String[] beanNamesForType = super.getBeanNamesForType(requiredType, false, false);
if (ArrayUtils.isNotEmpty(beanNamesForType)) {
return getBean(beanNamesForType[0], requiredType);
} else {
return beanContext.getBean(requiredType);
}
} catch (NoSuchBeanException e) {
throw new NoSuchBeanDefinitionException(requiredType, e.getMessage());
}
}
@Override
public @NonNull
T getBean(@NonNull Class requiredType, @NonNull Object... args) throws BeansException {
try {
return beanContext.createBean(requiredType, args);
} catch (NoSuchBeanException e) {
throw new NoSuchBeanDefinitionException(requiredType, e.getMessage());
}
}
@Override
public @NonNull
ObjectProvider getBeanProvider(@NonNull Class requiredType) {
return new ObjectProvider() {
@Override
public T getObject(Object... args) throws BeansException {
return beanContext.createBean(requiredType, args);
}
@Override
public T getIfAvailable() throws BeansException {
if (beanContext.containsBean(requiredType)) {
return beanContext.getBean(requiredType);
}
return null;
}
@Override
public T getIfUnique() throws BeansException {
final Collection beansOfType = beanContext.getBeansOfType(requiredType);
if (beansOfType.size() == 1) {
return beansOfType.stream().findFirst().orElse(null);
}
return null;
}
@Override
public T getObject() throws BeansException {
return beanContext.getBean(requiredType);
}
@Override
public Stream stream() {
return Arrays.stream(getBeanNamesForType(requiredType)).map(name -> (T) getBean(name));
}
@Override
public Stream orderedStream() {
return stream().sorted(OrderComparator.INSTANCE);
}
};
}
@Override
public @NonNull
ObjectProvider getBeanProvider(@NonNull ResolvableType requiredType) {
final Class resolved = (Class) requiredType.resolve();
return getBeanProvider(resolved);
}
@Override
public boolean containsBean(@NonNull String name) {
return super.containsSingleton(name) ||
beanDefinitionMap.containsKey(name) ||
beanDefinitionsByName.containsKey(name) ||
isAlias(name);
}
@Override
public boolean isSingleton(@NonNull String name) throws NoSuchBeanDefinitionException {
if (super.containsSingleton(name)) {
return true;
} else {
final BeanDefinition> definition = beanDefinitionMap.get(name);
if (definition != null) {
return isSingleton(definition);
}
return false;
}
}
/**
* Is the definition singleton.
* @param definition The definition
* @return True if it is
*/
protected boolean isSingleton(@NonNull BeanDefinitionReference> definition) {
final AnnotationMetadata annotationMetadata = definition.getAnnotationMetadata();
return isSingleton(annotationMetadata);
}
@Override
public boolean isPrototype(@NonNull String name) throws NoSuchBeanDefinitionException {
if (super.containsSingleton(name)) {
return false;
}
final BeanDefinition> definition = beanDefinitionMap.get(name);
if (definition != null) {
final AnnotationMetadata annotationMetadata = definition.getAnnotationMetadata();
if (annotationMetadata.hasDeclaredStereotype(Prototype.class)) {
return true;
} else {
final boolean hasScope = annotationMetadata.getAnnotationNamesByStereotype(AnnotationUtil.SCOPE).isEmpty();
return !hasScope;
}
}
return false;
}
@Override
public boolean isTypeMatch(@NonNull String name, @NonNull ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
final Class> resolved = typeToMatch.resolve();
if (resolved != null) {
return isTypeMatch(name, resolved);
}
return false;
}
@Override
public boolean isTypeMatch(@NonNull String name, @NonNull Class> typeToMatch) throws NoSuchBeanDefinitionException {
final Class> beanType = getType(name);
if (beanType != null) {
return typeToMatch.isAssignableFrom(beanType);
}
return false;
}
@Override
public Class> getType(@NonNull String beanName) throws NoSuchBeanDefinitionException {
Optional> opt = beanTypeCache.get(beanName);
//noinspection OptionalAssignedToNull
if (opt == null) {
final BeanDefinition> definition = beanDefinitionMap.get(beanName);
if (definition != null) {
opt = Optional.of(definition.getBeanType());
} else {
beanName = transformedBeanName(beanName);
// Check manually registered singletons.
Object beanInstance = super.getSingleton(beanName, false);
if (beanInstance != null && !beanInstance.getClass().getSimpleName().equals("NullBean")) {
if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(beanName)) {
return getTypeForFactoryBean((FactoryBean>) beanInstance);
} else {
return beanInstance.getClass();
}
}
// No singleton instance found -> check bean definition.
org.springframework.beans.factory.BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// No bean definition found in this factory -> delegate to parent.
return parentBeanFactory.getType(originalBeanName(beanName));
}
final org.springframework.beans.factory.config.BeanDefinition parentDef;
try {
parentDef = super.getBeanDefinition(beanName);
} catch (NoSuchBeanDefinitionException e) {
beanTypeCache.put(beanName, Optional.empty());
return null;
}
if (parentDef instanceof RootBeanDefinition) {
RootBeanDefinition mbd = (RootBeanDefinition) parentDef;
// Check decorated bean definition, if any: We assume it'll be easier
// to determine the decorated bean's type than the proxy's type.
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
if (dbd != null && !BeanFactoryUtils.isFactoryDereference(beanName)) {
RootBeanDefinition tbd = super.getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
Class> targetClass = predictBeanType(dbd.getBeanName(), tbd);
if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
return targetClass;
}
}
Class> beanClass = predictBeanType(beanName, mbd);
// Check bean class whether we're dealing with a FactoryBean.
if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) {
if (!BeanFactoryUtils.isFactoryDereference(beanName)) {
// If it's a FactoryBean, we want to look at what it creates, not at the factory class.
boolean allowInit = true; // if allowInit is true a full creation of the FactoryBean is used as fallback (through delegation to the superclass's implementation).
ResolvableType resolvableType = super.getTypeForFactoryBean(beanName, mbd, allowInit);
return resolvableType.getRawClass();
} else {
return beanClass;
}
} else {
return (!BeanFactoryUtils.isFactoryDereference(beanName) ? beanClass : null);
}
}
}
beanTypeCache.put(beanName, opt);
}
return opt.orElse(null);
}
@Override
public boolean containsBeanDefinition(@NonNull String beanName) {
return beanDefinitionMap.containsKey(beanName);
}
@Override
public int getBeanDefinitionCount() {
return beanDefinitionMap.size();
}
@Override
public @NonNull
String[] getBeanDefinitionNames() {
return beanDefinitionMap.keySet().toArray(new String[0]);
}
@Override
public @NonNull
String[] getBeanNamesForType(@NonNull ResolvableType type) {
final Class> resolved = type.resolve();
if (resolved != null) {
return getBeanNamesForType(resolved);
}
return StringUtils.EMPTY_STRING_ARRAY;
}
@Override
public @NonNull
String[] getBeanNamesForType(Class> type) {
return getBeanNamesForType(type, true, true);
}
@Override
public @NonNull
String[] getBeanNamesForType(Class> type, boolean includeNonSingletons, boolean allowEagerInit) {
// ignore certain common cases
if (type == null || Object.class == type || List.class == type || beanExcludes.contains(type)) {
return StringUtils.EMPTY_STRING_ARRAY;
}
String[] names = beanNamesForTypeCache.get(type);
if (names == null) {
final String[] superResult = MicronautBeanFactory.super.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
if (ArrayUtils.isNotEmpty(superResult)) {
names = superResult;
} else {
final Collection extends BeanDefinition>> beanDefinitions = beanContext.getBeanDefinitions(type);
names = beansToNames(beanDefinitions);
}
beanNamesForTypeCache.put(type, names);
}
return names;
}
@Override
public @NonNull
Map getBeansOfType(Class type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException {
if (type == null || beanExcludes.contains(type)) {
return Collections.emptyMap();
}
final Map springSingletons = super.getBeansOfType(type, false, false);
final Collection beansOfType = beanContext.getBeansOfType(type);
Map beans = new HashMap<>(beansOfType.size());
beans.putAll(springSingletons);
for (T bean : beansOfType) {
if (!springSingletons.containsValue(bean)) {
final Optional> reg = beanContext.findBeanRegistration(bean);
reg.ifPresent(registration -> beans.put(registration.getBeanDefinition().getClass().getName(), bean));
}
}
return beans;
}
@Override
public @NonNull
String[] getBeanNamesForAnnotation(@NonNull Class extends Annotation> annotationType) {
final String[] beanNamesForAnnotation = super.getBeanNamesForAnnotation(annotationType);
final Collection> beanDefinitions = beanContext.getBeanDefinitions(Qualifiers.byStereotype(annotationType));
return ArrayUtils.concat(beansToNames(beanDefinitions), beanNamesForAnnotation);
}
@Override
public A findAnnotationOnBean(@NonNull String beanName, @NonNull Class annotationType) throws NoSuchBeanDefinitionException {
if (super.containsSingleton(beanName)) {
return super.findAnnotationOnBean(beanName, annotationType);
} else {
final BeanDefinition> ref = beanDefinitionMap.get(beanName);
if (ref != null) {
return ref.getAnnotationMetadata().synthesize(annotationType);
}
return null;
}
}
private String[] beansToNames(Collection extends BeanDefinition>> beanDefinitions) {
return beanDefinitions.stream()
.filter(bd -> !(bd instanceof ParametrizedInstantiatableBeanDefinition))
.map(this::computeBeanName).toArray(String[]::new);
}
@Override
public @NonNull
T createBean(@NonNull Class beanClass) throws BeansException {
return beanContext.createBean(beanClass);
}
@SuppressWarnings("ConstantConditions")
@Override
public void autowireBean(@NonNull Object existingBean) throws BeansException {
if (existingBean != null) {
beanContext.inject(existingBean);
}
}
@Override
public Object configureBean(Object existingBean, String beanName) throws BeansException {
final Object injected = beanContext.inject(existingBean);
return initializeBean(injected, beanName);
}
@Override
public Object createBean(Class> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
return createBean(beanClass);
}
@Override
public Object autowire(Class> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
return beanContext.getBean(beanClass);
}
@Override
public void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException {
autowireBean(existingBean);
}
@Override
public void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException {
autowireBean(existingBean);
}
@Override
public Object initializeBean(Object existingBean, String beanName) throws BeansException {
return springAwareListener.onBeanCreated(null, existingBean, beanName);
}
@Override
public void destroyBean(Object existingBean) {
if (existingBean instanceof Closeable) {
try {
((Closeable) existingBean).close();
} catch (Exception e) {
if (logger.isDebugEnabled()) {
logger.debug("Invocation of destroy method failed for bean [" + existingBean + "]: " + e.getMessage(), e);
}
}
} else if (existingBean instanceof DisposableBean) {
try {
((DisposableBean) existingBean).destroy();
} catch (Exception e) {
if (logger.isDebugEnabled()) {
logger.debug("Invocation of destroy method failed for bean [" + existingBean + "]: " + e.getMessage(), e);
}
}
} else if (existingBean instanceof AutoCloseable) {
try {
((AutoCloseable) existingBean).close();
} catch (Exception e) {
if (logger.isDebugEnabled()) {
logger.debug("Invocation of destroy method failed for bean [" + existingBean + "]: " + e.getMessage(), e);
}
}
}
}
@Override
public boolean containsLocalBean(String name) {
return super.containsLocalBean(name) || beanDefinitionMap.containsKey(name) || beanDefinitionsByName.containsKey(name);
}
/**
* @return The backing Micronaut bean context.
*/
public BeanContext getBeanContext() {
return beanContext;
}
@Override
public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor) throws NoSuchBeanDefinitionException {
return false;
}
@Override
public org.springframework.beans.factory.config.BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
final BeanDefinition> definition = beanDefinitionMap.get(beanName);
if (definition != null && definition.isEnabled(beanContext)) {
final GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
genericBeanDefinition.setBeanClass(definition.getBeanType());
int role = definition.intValue(Role.class).orElse(org.springframework.beans.factory.config.BeanDefinition.ROLE_APPLICATION);
genericBeanDefinition.setRole(role);
return genericBeanDefinition;
}
throw new NoSuchBeanDefinitionException(beanName);
}
@SuppressWarnings("unchecked")
@Override
protected T doGetBean(String name, Class requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
if (beanExcludes.contains(requiredType)) {
throw new NoSuchBeanDefinitionException(name);
}
if (super.containsSingleton(name)) {
final Object o = super.getSingleton(name);
if (requiredType == null || requiredType.isInstance(o)) {
return (T) o;
}
}
BeanDefinition> definition = beanDefinitionMap.get(name);
if (definition == null) {
// by name, with no type lookups
final BeanDefinition> def = beanDefinitionsByName.get(name);
if (def != null) {
if (requiredType != null) {
if (requiredType.isAssignableFrom(def.getBeanType())) {
definition = def;
}
} else {
definition = def;
}
}
}
if (definition != null && definition.isEnabled(beanContext)) {
if (requiredType == null) {
requiredType = (Class) definition.getBeanType();
}
BeanDefinition> finalDefinition = definition;
io.micronaut.context.Qualifier q = (io.micronaut.context.Qualifier) definition.getValue(AnnotationUtil.NAMED, String.class)
.map((String n) -> {
if (Primary.class.getName().equals(n)) {
return n;
}
return Qualifiers.byName(n);
})
.orElseGet(() -> {
if (finalDefinition.hasDeclaredStereotype(Primary.class)) {
return null;
}
final String annotationType = finalDefinition.getAnnotationNameByStereotype(AnnotationUtil.QUALIFIER).orElse(null);
if (annotationType != null) {
return Qualifiers.byAnnotation(finalDefinition, annotationType);
} else if (finalDefinition instanceof NameResolver) {
return ((NameResolver) finalDefinition).resolveName().map(Qualifiers::byName).orElse(null);
}
return null;
}
);
if (q != null) {
return beanContext.getBean(requiredType, q);
} else {
return beanContext.getBean(requiredType);
}
}
final org.springframework.beans.factory.BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null) {
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).getBean(
name, requiredType, args);
} else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(name, args);
} else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(name, requiredType);
} else {
return (T) parentBeanFactory.getBean(name);
}
}
if (requiredType != null) {
try {
return beanContext.getBean(requiredType, Qualifiers.byName(name));
} catch (NoSuchBeanException e) {
throw new NoSuchBeanDefinitionException(name);
}
} else {
throw new NoSuchBeanDefinitionException(name);
}
}
@Override
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
if (super.containsSingleton(beanName)) {
return super.getSingleton(beanName, allowEarlyReference);
} else {
return getBean(beanName);
}
}
@Override
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
if (super.containsSingleton(beanName)) {
return super.getSingleton(beanName, singletonFactory);
} else {
return getBean(beanName);
}
}
@Override
public Iterator getBeanNamesIterator() {
return Arrays.asList(getBeanDefinitionNames()).iterator();
}
@Override
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
return false;
}
@Override
public void destroyBean(String beanName, Object beanInstance) {
final BeanDefinition> definition = beanDefinitionMap.get(beanName);
if (definition instanceof DisposableBeanDefinition) {
((DisposableBeanDefinition) definition).dispose(beanContext, beanInstance);
}
}
@Override
public void registerSingleton(String beanName, Object singletonObject) {
final Class type = singletonObject.getClass();
beanContext.registerSingleton(
type,
singletonObject,
Qualifiers.byName(beanName)
);
super.registerSingleton(beanName, singletonObject);
}
@Override
public boolean containsSingleton(String beanName) {
return isSingleton(beanName);
}
@Override
public void registerBeanDefinition(String beanName, org.springframework.beans.factory.config.BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
if (beanDefinition instanceof org.springframework.beans.factory.support.AbstractBeanDefinition) {
org.springframework.beans.factory.support.AbstractBeanDefinition abstractBeanDefinition = (org.springframework.beans.factory.support.AbstractBeanDefinition) beanDefinition;
final Supplier