Spring Framework 源码解析课程大纲

首先明确我们读Spring Framework的源码的目的是什么?

是为了显示自己很牛X么?

Spring源码阅读的难度在于其呢内容庞大,并不是里面有很复杂的算法,需要高智商才能理解。所以你搞懂了Spring的源码并不能说明你有多聪明,但是能证明你具有上进心和耐心,从而花了大量的时间来学习Spring的源码。

1、学习Spring Framework的内部原理
2、学习优秀的设计思想(比如设计模式的应用)
3、基于Spring的生态开发中间件
4、学习Spring Boot、Spring Cloud内部原理

如果基于Spring来开发中间件,想知道如何将功能集成到Spring中就必须了解Spring的内部原理

/*

  • Copyright 2002-2019 the original author or 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
  •  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.springframework.beans.factory.support;

import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
import javax.inject.Provider;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.CannotLoadBeanClassException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InjectionPoint;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.NamedBeanHolder;
import org.springframework.core.OrderComparator;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CompositeIterator;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**

  • Spring’s default implementation of the {@link ConfigurableListableBeanFactory}

  • and {@link BeanDefinitionRegistry} interfaces: a full-fledged bean factory

  • based on bean definition metadata, extensible through post-processors.

  • Typical usage is registering all bean definitions first (possibly read

  • from a bean definition file), before accessing beans. Bean lookup by name

  • is therefore an inexpensive operation in a local bean definition table,

  • operating on pre-resolved bean definition metadata objects.

  • Note that readers for specific bean definition formats are typically

  • implemented separately rather than as bean factory subclasses:

  • see for example {@link PropertiesBeanDefinitionReader} and

  • {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.

  • For an alternative implementation of the

  • {@link org.springframework.beans.factory.ListableBeanFactory} interface,

  • have a look at {@link StaticListableBeanFactory}, which manages existing

  • bean instances rather than creating new ones based on bean definitions.

  • @author Rod Johnson

  • @author Juergen Hoeller

  • @author Sam Brannen

  • @author Costin Leau

  • @author Chris Beams

  • @author Phillip Webb

  • @author Stephane Nicoll

  • @since 16 April 2001

  • @see #registerBeanDefinition

  • @see #addBeanPostProcessor

  • @see #getBean

  • @see #resolveDependency
    */
    @SuppressWarnings(“serial”)
    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
    implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

    @Nullable
    private static Class<?> javaxInjectProviderClass;

    static {
    try {
    javaxInjectProviderClass =
    ClassUtils.forName(“javax.inject.Provider”, DefaultListableBeanFactory.class.getClassLoader());
    }
    catch (ClassNotFoundException ex) {
    // JSR-330 API not available - Provider interface simply not supported then.
    javaxInjectProviderClass = null;
    }
    }

    /** Map from serialized id to factory instance. */
    private static final Map<String, Reference> serializableFactories =
    new ConcurrentHashMap<>(8);

    /** Optional id for this factory, for serialization purposes. */
    @Nullable
    private String serializationId;

    /** Whether to allow re-registration of a different definition with the same name. */
    private boolean allowBeanDefinitionOverriding = true;

    /** Whether to allow eager class loading even for lazy-init beans. */
    private boolean allowEagerClassLoading = true;

    /** Optional OrderComparator for dependency Lists and arrays. */
    @Nullable
    private Comparator dependencyComparator;

    /** Resolver to use for checking if a bean definition is an autowire candidate. */
    private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();

    /** Map from dependency type to corresponding autowired value. */
    private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

    /** Map of bean definition objects, keyed by bean name. */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

    /** Map of singleton and non-singleton bean names, keyed by dependency type. */
    private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

    /** Map of singleton-only bean names, keyed by dependency type. */
    private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

    /** List of bean definition names, in registration order. */
    private volatile List beanDefinitionNames = new ArrayList<>(256);

    /** List of names of manually registered singletons, in registration order. */
    private volatile Set manualSingletonNames = new LinkedHashSet<>(16);

    /** Cached array of bean definition names in case of frozen configuration. */
    @Nullable
    private volatile String[] frozenBeanDefinitionNames;

    /** Whether bean definition metadata may be cached for all beans. */
    private volatile boolean configurationFrozen = false;

    /**

    • Create a new DefaultListableBeanFactory.
      */
      public DefaultListableBeanFactory() {
      super();
      }

    /**

    • Create a new DefaultListableBeanFactory with the given parent.
    • @param parentBeanFactory the parent BeanFactory
      */
      public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
      super(parentBeanFactory);
      }

    /**

    • Specify an id for serialization purposes, allowing this BeanFactory to be
    • deserialized from this id back into the BeanFactory object, if needed.
      */
      public void setSerializationId(@Nullable String serializationId) {
      if (serializationId != null) {
      serializableFactories.put(serializationId, new WeakReference<>(this));
      }
      else if (this.serializationId != null) {
      serializableFactories.remove(this.serializationId);
      }
      this.serializationId = serializationId;
      }

    /**

    • Return an id for serialization purposes, if specified, allowing this BeanFactory
    • to be deserialized from this id back into the BeanFactory object, if needed.
    • @since 4.1.2
      */
      @Nullable
      public String getSerializationId() {
      return this.serializationId;
      }

    /**

    • Set whether it should be allowed to override bean definitions by registering
    • a different definition with the same name, automatically replacing the former.
    • If not, an exception will be thrown. This also applies to overriding aliases.
    • Default is "true".

    • @see #registerBeanDefinition
      */
      public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
      this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
      }

    /**

    • Return whether it should be allowed to override bean definitions by registering
    • a different definition with the same name, automatically replacing the former.
    • @since 4.1.2
      */
      public boolean isAllowBeanDefinitionOverriding() {
      return this.allowBeanDefinitionOverriding;
      }

    /**

    • Set whether the factory is allowed to eagerly load bean classes
    • even for bean definitions that are marked as “lazy-init”.
    • Default is "true". Turn this flag off to suppress class loading

    • for lazy-init beans unless such a bean is explicitly requested.
    • In particular, by-type lookups will then simply ignore bean definitions
    • without resolved class name, instead of loading the bean classes on
    • demand just to perform a type check.
    • @see AbstractBeanDefinition#setLazyInit
      */
      public void setAllowEagerClassLoading(boolean allowEagerClassLoading) {
      this.allowEagerClassLoading = allowEagerClassLoading;
      }

    /**

    • Return whether the factory is allowed to eagerly load bean classes
    • even for bean definitions that are marked as “lazy-init”.
    • @since 4.1.2
      */
      public boolean isAllowEagerClassLoading() {
      return this.allowEagerClassLoading;
      }

    /**

    • Set a {@link java.util.Comparator} for dependency Lists and arrays.
    • @since 4.0
    • @see org.springframework.core.OrderComparator
    • @see org.springframework.core.annotation.AnnotationAwareOrderComparator
      */
    m1
    public void setDependencyComparator(@Nullable Comparator dependencyComparator) { this.dependencyComparator = dependencyComparator; }

    /**

    • Return the dependency comparator for this BeanFactory (may be {@code null}.
    • @since 4.0
      */
      @Nullable
      public Comparator getDependencyComparator() {
      return this.dependencyComparator;
      }

    /**

    • Set a custom autowire candidate resolver for this BeanFactory to use
    • when deciding whether a bean definition should be considered as a
    • candidate for autowiring.
      */
      public void setAutowireCandidateResolver(final AutowireCandidateResolver autowireCandidateResolver) {
      Assert.notNull(autowireCandidateResolver, “AutowireCandidateResolver must not be null”);
      if (autowireCandidateResolver instanceof BeanFactoryAware) {
      if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction) () -> {
      ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(DefaultListableBeanFactory.this);
      return null;
      }, getAccessControlContext());
      }
      else {
      ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
      }
      }
      this.autowireCandidateResolver = autowireCandidateResolver;
      }

    /**

    • Return the autowire candidate resolver for this BeanFactory (never {@code null}).
      */
      public AutowireCandidateResolver getAutowireCandidateResolver() {
      return this.autowireCandidateResolver;
      }

    @Override
    public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
    super.copyConfigurationFrom(otherFactory);
    if (otherFactory instanceof DefaultListableBeanFactory) {
    DefaultListableBeanFactory otherListableFactory = (DefaultListableBeanFactory) otherFactory;
    this.allowBeanDefinitionOverriding = otherListableFactory.allowBeanDefinitionOverriding;
    this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading;
    this.dependencyComparator = otherListableFactory.dependencyComparator;
    // A clone of the AutowireCandidateResolver since it is potentially BeanFactoryAware…
    setAutowireCandidateResolver(BeanUtils.instantiateClass(getAutowireCandidateResolver().getClass()));
    // Make resolvable dependencies (e.g. ResourceLoader) available here as well…
    this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies);
    }
    }

    //---------------------------------------------------------------------
    // Implementation of remaining BeanFactory methods
    //---------------------------------------------------------------------

    @Override
    public T getBean(Class requiredType) throws BeansException {
    return getBean(requiredType, (Object[]) null);
    }

    @SuppressWarnings(“unchecked”)
    @Override
    public T getBean(Class requiredType, @Nullable Object… args) throws BeansException {
    Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
    if (resolved == null) {
    throw new NoSuchBeanDefinitionException(requiredType);
    }
    return (T) resolved;
    }

m2
@Override public ObjectProvider getBeanProvider(Class requiredType) throws BeansException { return getBeanProvider(ResolvableType.forRawClass(requiredType)); }
@SuppressWarnings("unchecked")
@Override
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
	return new BeanObjectProvider<T>() {
		@Override
		public T getObject() throws BeansException {
			T resolved = resolveBean(requiredType, null, false);
			if (resolved == null) {
				throw new NoSuchBeanDefinitionException(requiredType);
			}
			return resolved;
		}
		@Override
		public T getObject(Object... args) throws BeansException {
			T resolved = resolveBean(requiredType, args, false);
			if (resolved == null) {
				throw new NoSuchBeanDefinitionException(requiredType);
			}
			return resolved;
		}
		@Override
		@Nullable
		public T getIfAvailable() throws BeansException {
			return resolveBean(requiredType, null, false);
		}
		@Override
		@Nullable
		public T getIfUnique() throws BeansException {
			return resolveBean(requiredType, null, true);
		}
		@Override
		public Stream<T> stream() {
			return Arrays.stream(getBeanNamesForTypedStream(requiredType))
					.map(name -> (T) getBean(name))
					.filter(bean -> !(bean instanceof NullBean));
		}
		@Override
		public Stream<T> orderedStream() {
			String[] beanNames = getBeanNamesForTypedStream(requiredType);
			Map<String, T> matchingBeans = new LinkedHashMap<>(beanNames.length);
			for (String beanName : beanNames) {
				Object beanInstance = getBean(beanName);
				if (!(beanInstance instanceof NullBean)) {
					matchingBeans.put(beanName, (T) beanInstance);
				}
			}
			Stream<T> stream = matchingBeans.values().stream();
			return stream.sorted(adaptOrderComparator(matchingBeans));
		}
	};
}

@Nullable
private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
	NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
	if (namedBean != null) {
		return namedBean.getBeanInstance();
	}
	BeanFactory parent = getParentBeanFactory();
	if (parent instanceof DefaultListableBeanFactory) {
		return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull);
	}
	else if (parent != null) {
		ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
		if (args != null) {
			return parentProvider.getObject(args);
		}
		else {
			return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
		}
	}
	return null;
}

private String[] getBeanNamesForTypedStream(ResolvableType requiredType) {
	return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType);
}


//---------------------------------------------------------------------
// Implementation of ListableBeanFactory interface
//---------------------------------------------------------------------

@Override
public boolean containsBeanDefinition(String beanName) {
	Assert.notNull(beanName, "Bean name must not be null");
	return this.beanDefinitionMap.containsKey(beanName);
}

@Override
public int getBeanDefinitionCount() {
	return this.beanDefinitionMap.size();
}

@Override
public String[] getBeanDefinitionNames() {
	String[] frozenNames = this.frozenBeanDefinitionNames;
	if (frozenNames != null) {
		return frozenNames.clone();
	}
	else {
		return StringUtils.toStringArray(this.beanDefinitionNames);
	}
}

@Override
public String[] getBeanNamesForType(ResolvableType type) {
	Class<?> resolved = type.resolve();
	if (resolved != null && !type.hasGenerics()) {
		return getBeanNamesForType(resolved, true, true);
	}
	else {
		return doGetBeanNamesForType(type, true, true);
	}
}

@Override
public String[] getBeanNamesForType(@Nullable Class<?> type) {
	return getBeanNamesForType(type, true, true);
}

@Override
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
	if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
		return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
	}
	Map<Class<?>, String[]> cache =
			(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
	String[] resolvedBeanNames = cache.get(type);
	if (resolvedBeanNames != null) {
		return resolvedBeanNames;
	}
	resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
	if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
		cache.put(type, resolvedBeanNames);
	}
	return resolvedBeanNames;
}

private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
	List<String> result = new ArrayList<>();

	// Check all bean definitions.
	for (String beanName : this.beanDefinitionNames) {
		// Only consider bean as eligible if the bean name
		// is not defined as alias for some other bean.
		if (!isAlias(beanName)) {
			try {
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				// Only check bean definition if it is complete.
				if (!mbd.isAbstract() && (allowEagerInit ||
						(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
								!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
					// In case of FactoryBean, match object created by FactoryBean.
					boolean isFactoryBean = isFactoryBean(beanName, mbd);
					BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
					boolean matchFound =
							(allowEagerInit || !isFactoryBean ||
									(dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
							(includeNonSingletons ||
									(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
							isTypeMatch(beanName, type);
					if (!matchFound && isFactoryBean) {
						// In case of FactoryBean, try to match FactoryBean instance itself next.
						beanName = FACTORY_BEAN_PREFIX + beanName;
						matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
					}
					if (matchFound) {
						result.add(beanName);
					}
				}
			}
			catch (CannotLoadBeanClassException ex) {
				if (allowEagerInit) {
					throw ex;
				}
				// Probably a class name with a placeholder: let's ignore it for type matching purposes.
				if (logger.isTraceEnabled()) {
					logger.trace("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
				}
				onSuppressedException(ex);
			}
			catch (BeanDefinitionStoreException ex) {
				if (allowEagerInit) {
					throw ex;
				}
				// Probably some metadata with a placeholder: let's ignore it for type matching purposes.
				if (logger.isTraceEnabled()) {
					logger.trace("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
				}
				onSuppressedException(ex);
			}
		}
	}

	// Check manually registered singletons too.
	for (String beanName : this.manualSingletonNames) {
		try {
			// In case of FactoryBean, match object created by FactoryBean.
			if (isFactoryBean(beanName)) {
				if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
					result.add(beanName);
					// Match found for this bean: do not match FactoryBean itself anymore.
					continue;
				}
				// In case of FactoryBean, try to match FactoryBean itself next.
				beanName = FACTORY_BEAN_PREFIX + beanName;
			}
			// Match raw bean instance (might be raw FactoryBean).
			if (isTypeMatch(beanName, type)) {
				result.add(beanName);
			}
		}
		<div id="m3">m3</div>
		catch (NoSuchBeanDefinitionException ex) {
			// Shouldn't happen - probably a result of circular reference resolution...
			if (logger.isTraceEnabled()) {
				logger.trace("Failed to check manually registered singleton with name '" + beanName + "'", ex);
			}
		}
	}

	return StringUtils.toStringArray(result);
}

/**
 * Check whether the specified bean would need to be eagerly initialized
 * in order to determine its type.
 * @param factoryBeanName a factory-bean reference that the bean definition
 * defines a factory method for
 * @return whether eager initialization is necessary
 */
private boolean requiresEagerInitForType(@Nullable String factoryBeanName) {
	return (factoryBeanName != null && isFactoryBean(factoryBeanName) && !containsSingleton(factoryBeanName));
}

@Override
public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException {
	return getBeansOfType(type, true, true);
}

@Override
@SuppressWarnings("unchecked")
public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
		throws BeansException {

	String[] beanNames = getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
	Map<String, T> result = new LinkedHashMap<>(beanNames.length);
	for (String beanName : beanNames) {
		try {
			Object beanInstance = getBean(beanName);
			if (!(beanInstance instanceof NullBean)) {
				result.put(beanName, (T) beanInstance);
			}
		}
		catch (BeanCreationException ex) {
			Throwable rootCause = ex.getMostSpecificCause();
			if (rootCause instanceof BeanCurrentlyInCreationException) {
				BeanCreationException bce = (BeanCreationException) rootCause;
				String exBeanName = bce.getBeanName();
				if (exBeanName != null && isCurrentlyInCreation(exBeanName)) {
					if (logger.isTraceEnabled()) {
						logger.trace("Ignoring match to currently created bean '" + exBeanName + "': " +
								ex.getMessage());
					}
					onSuppressedException(ex);
					// Ignore: indicates a circular reference when autowiring constructors.
					// We want to find matches other than the currently created bean itself.
					continue;
				}
			}
			throw ex;
		}
	}
	return result;
}

@Override
public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
	List<String> result = new ArrayList<>();
	for (String beanName : this.beanDefinitionNames) {
		BeanDefinition beanDefinition = getBeanDefinition(beanName);
		if (!beanDefinition.isAbstract() && findAnnotationOnBean(beanName, annotationType) != null) {
			result.add(beanName);
		}
	}
	for (String beanName : this.manualSingletonNames) {
		if (!result.contains(beanName) && findAnnotationOnBean(beanName, annotationType) != null) {
			result.add(beanName);
		}
	}
	return StringUtils.toStringArray(result);
}

@Override
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
	String[] beanNames = getBeanNamesForAnnotation(annotationType);
	Map<String, Object> result = new LinkedHashMap<>(beanNames.length);
	for (String beanName : beanNames) {
		Object beanInstance = getBean(beanName);
		if (!(beanInstance instanceof NullBean)) {
			result.put(beanName, beanInstance);
		}
	}
	return result;
}

/**
 * Find a {@link Annotation} of {@code annotationType} on the specified
 * bean, traversing its interfaces and super classes if no annotation can be
 * found on the given class itself, as well as checking its raw bean class
 * if not found on the exposed bean reference (e.g. in case of a proxy).
 */
@Override
@Nullable
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
		throws NoSuchBeanDefinitionException {

	A ann = null;
	Class<?> beanType = getType(beanName);
	if (beanType != null) {
		ann = AnnotationUtils.findAnnotation(beanType, annotationType);
	}
	if (ann == null && containsBeanDefinition(beanName)) {
		BeanDefinition bd = getMergedBeanDefinition(beanName);
		if (bd instanceof AbstractBeanDefinition) {
			AbstractBeanDefinition abd = (AbstractBeanDefinition) bd;
			if (abd.hasBeanClass()) {
				Class<?> beanClass = abd.getBeanClass();
				if (beanClass != beanType) {
					ann = AnnotationUtils.findAnnotation(beanClass, annotationType);
				}
			}
		}
	}
	return ann;
}


//---------------------------------------------------------------------
// Implementation of ConfigurableListableBeanFactory interface
//---------------------------------------------------------------------

@Override
public void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue) {
	Assert.notNull(dependencyType, "Dependency type must not be null");
	if (autowiredValue != null) {
		if (!(autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue))) {
			throw new IllegalArgumentException("Value [" + autowiredValue +
					"] does not implement specified dependency type [" + dependencyType.getName() + "]");
		}
		this.resolvableDependencies.put(dependencyType, autowiredValue);
	}
}

@Override
public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
		throws NoSuchBeanDefinitionException {

	return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver());
}

/**
 * Determine whether the specified bean definition qualifies as an autowire candidate,
 * to be injected into other beans which declare a dependency of matching type.
 * @param beanName the name of the bean definition to check
 * @param descriptor the descriptor of the dependency to resolve
 * @param resolver the AutowireCandidateResolver to use for the actual resolution algorithm
 * @return whether the bean should be considered as autowire candidate
 */
protected boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor, AutowireCandidateResolver resolver)
		throws NoSuchBeanDefinitionException {

	String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
	if (containsBeanDefinition(beanDefinitionName)) {
		return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanDefinitionName), descriptor, resolver);
	}
	else if (containsSingleton(beanName)) {
		return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
	}

	BeanFactory parent = getParentBeanFactory();
	if (parent instanceof DefaultListableBeanFactory) {
		// No bean definition found in this factory -> delegate to parent.
		return ((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor, resolver);
	}
	else if (parent instanceof ConfigurableListableBeanFactory) {
		// If no DefaultListableBeanFactory, can't pass the resolver along.
		return ((ConfigurableListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor);
	}
	else {
		return true;
	}
}

/**
 * Determine whether the specified bean definition qualifies as an autowire candidate,
 * to be injected into other beans which declare a dependency of matching type.
 * @param beanName the name of the bean definition to check
 * @param mbd the merged bean definition to check
 * @param descriptor the descriptor of the dependency to resolve
 * @param resolver the AutowireCandidateResolver to use for the actual resolution algorithm
 * @return whether the bean should be considered as autowire candidate
 */
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd,
		DependencyDescriptor descriptor, AutowireCandidateResolver resolver) {

	String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
	resolveBeanClass(mbd, beanDefinitionName);
	if (mbd.isFactoryMethodUnique && mbd.factoryMethodToIntrospect == null) {
		new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
	}
	return resolver.isAutowireCandidate(
			new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)), descriptor);
}

@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
	BeanDefinition bd = this.beanDefinitionMap.get(beanName);
	if (bd == null) {
		if (logger.isTraceEnabled()) {
			logger.trace("No bean named '" + beanName + "' found in " + this);
		}
		throw new NoSuchBeanDefinitionException(beanName);
	}
	return bd;
}

@Override
public Iterator<String> getBeanNamesIterator() {
	CompositeIterator<String> iterator = new CompositeIterator<>();
	iterator.add(this.beanDefinitionNames.iterator());
	iterator.add(this.manualSingletonNames.iterator());
	return iterator;
}

@Override
public void clearMetadataCache() {
	super.clearMetadataCache();
	clearByTypeCache();
}

@Override
public void freezeConfiguration() {
	this.configurationFrozen = true;
	this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}

@Override
public boolean isConfigurationFrozen() {
	return this.configurationFrozen;
}

/**
 * Considers all beans as eligible for metadata caching
 * if the factory's configuration has been marked as frozen.
 * @see #freezeConfiguration()
 */
@Override
protected boolean isBeanEligibleForMetadataCaching(String beanName) {
	return (this.configurationFrozen || super.isBeanEligibleForMetadataCaching(beanName));
}

@Override
public void preInstantiateSingletons() throws BeansException {
	if (logger.isTraceEnabled()) {
		logger.trace("Pre-instantiating singletons in " + this);
	}

	// Iterate over a copy to allow for init methods which in turn register new bean definitions.
	// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

	// Trigger initialization of all non-lazy singleton beans...
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			if (isFactoryBean(beanName)) {
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
				if (bean instanceof FactoryBean) {
					final FactoryBean<?> factory = (FactoryBean<?>) bean;
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
										((SmartFactoryBean<?>) factory)::isEagerInit,
								getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
						getBean(beanName);
					}
				}
			}
			else {
				getBean(beanName);
			}
		}
	}

	// Trigger post-initialization callback for all applicable beans...
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
		if (singletonInstance instanceof SmartInitializingSingleton) {
			final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					smartSingleton.afterSingletonsInstantiated();
					return null;
				}, getAccessControlContext());
			}
			else {
				smartSingleton.afterSingletonsInstantiated();
			}
		}
	}
}


//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
		throws BeanDefinitionStoreException {

	Assert.hasText(beanName, "Bean name must not be empty");
	Assert.notNull(beanDefinition, "BeanDefinition must not be null");

	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Validation of bean definition failed", ex);
		}
	}

	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		}
		else if (existingDefinition.getRole() < beanDefinition.getRole()) {
			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
			if (logger.isInfoEnabled()) {
				logger.info("Overriding user-defined bean definition for bean '" + beanName +
						"' with a framework-generated bean definition: replacing [" +
						existingDefinition + "] with [" + beanDefinition + "]");
			}
		}
		else if (!beanDefinition.equals(existingDefinition)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Overriding bean definition for bean '" + beanName +
						"' with a different definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
	else {
		if (hasBeanCreationStarted()) {
			// Cannot modify startup-time collection elements anymore (for stable iteration)
			synchronized (this.beanDefinitionMap) {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				if (this.manualSingletonNames.contains(beanName)) {
					Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
					updatedSingletons.remove(beanName);
					this.manualSingletonNames = updatedSingletons;
				}
			}
		}
		else {
			// Still in startup registration phase
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			this.manualSingletonNames.remove(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

	if (existingDefinition != null || containsSingleton(beanName)) {
		resetBeanDefinition(beanName);
	}
}

@Override
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
	Assert.hasText(beanName, "'beanName' must not be empty");

	BeanDefinition bd = this.beanDefinitionMap.remove(beanName);
	if (bd == null) {
		if (logger.isTraceEnabled()) {
			logger.trace("No bean named '" + beanName + "' found in " + this);
		}
		throw new NoSuchBeanDefinitionException(beanName);
	}

	if (hasBeanCreationStarted()) {
		// Cannot modify startup-time collection elements anymore (for stable iteration)
		synchronized (this.beanDefinitionMap) {
			List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames);
			updatedDefinitions.remove(beanName);
			this.beanDefinitionNames = updatedDefinitions;
		}
	}
	else {
		// Still in startup registration phase
		this.beanDefinitionNames.remove(beanName);
	}
	this.frozenBeanDefinitionNames = null;

	resetBeanDefinition(beanName);
}

/**
 * Reset all bean definition caches for the given bean,
 * including the caches of beans that are derived from it.
 * <p>Called after an existing bean definition has been replaced or removed,
 * triggering {@link #clearMergedBeanDefinition}, {@link #destroySingleton}
 * and {@link MergedBeanDefinitionPostProcessor#resetBeanDefinition} on the
 * given bean and on all bean definitions that have the given bean as parent.
 * @param beanName the name of the bean to reset
 * @see #registerBeanDefinition
 * @see #removeBeanDefinition
 */
protected void resetBeanDefinition(String beanName) {
	// Remove the merged bean definition for the given bean, if already created.
	clearMergedBeanDefinition(beanName);

	// Remove corresponding bean from singleton cache, if any. Shouldn't usually
	// be necessary, rather just meant for overriding a context's default beans
	// (e.g. the default StaticMessageSource in a StaticApplicationContext).
	destroySingleton(beanName);

	// Notify all post-processors that the specified bean definition has been reset.
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		if (processor instanceof MergedBeanDefinitionPostProcessor) {
			((MergedBeanDefinitionPostProcessor) processor).resetBeanDefinition(beanName);
		}
	}

	// Reset all bean definitions that have the given bean as parent (recursively).
	for (String bdName : this.beanDefinitionNames) {
		if (!beanName.equals(bdName)) {
			BeanDefinition bd = this.beanDefinitionMap.get(bdName);
			if (beanName.equals(bd.getParentName())) {
				resetBeanDefinition(bdName);
			}
		}
	}
}

/**
 * Only allows alias overriding if bean definition overriding is allowed.
 */
@Override
protected boolean allowAliasOverriding() {
	return isAllowBeanDefinitionOverriding();
}

@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
	super.registerSingleton(beanName, singletonObject);

	if (hasBeanCreationStarted()) {
		// Cannot modify startup-time collection elements anymore (for stable iteration)
		synchronized (this.beanDefinitionMap) {
			if (!this.beanDefinitionMap.containsKey(beanName)) {
				Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames.size() + 1);
				updatedSingletons.addAll(this.manualSingletonNames);
				updatedSingletons.add(beanName);
				this.manualSingletonNames = updatedSingletons;
			}
		}
	}
	else {
		// Still in startup registration phase
		if (!this.beanDefinitionMap.containsKey(beanName)) {
			this.manualSingletonNames.add(beanName);
		}
	}

	clearByTypeCache();
}

@Override
public void destroySingleton(String beanName) {
	super.destroySingleton(beanName);
	this.manualSingletonNames.remove(beanName);
	clearByTypeCache();
}

@Override
public void destroySingletons() {
	super.destroySingletons();
	this.manualSingletonNames.clear();
	clearByTypeCache();
}

/**
 * Remove any assumptions about by-type mappings.
 */
private void clearByTypeCache() {
	this.allBeanNamesByType.clear();
	this.singletonBeanNamesByType.clear();
}


//---------------------------------------------------------------------
// Dependency resolution functionality
//---------------------------------------------------------------------

@Override
public <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException {
	NamedBeanHolder<T> namedBean = resolveNamedBean(ResolvableType.forRawClass(requiredType), null, false);
	if (namedBean != null) {
		return namedBean;
	}
	BeanFactory parent = getParentBeanFactory();
	if (parent instanceof AutowireCapableBeanFactory) {
		return ((AutowireCapableBeanFactory) parent).resolveNamedBean(requiredType);
	}
	throw new NoSuchBeanDefinitionException(requiredType);
}

@SuppressWarnings("unchecked")
@Nullable
private <T> NamedBeanHolder<T> resolveNamedBean(
		ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {

	Assert.notNull(requiredType, "Required type must not be null");
	String[] candidateNames = getBeanNamesForType(requiredType);

	if (candidateNames.length > 1) {
		List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
		for (String beanName : candidateNames) {
			if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
				autowireCandidates.add(beanName);
			}
		}
		if (!autowireCandidates.isEmpty()) {
			candidateNames = StringUtils.toStringArray(autowireCandidates);
		}
	}

	if (candidateNames.length == 1) {
		String beanName = candidateNames[0];
		return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
	}
	else if (candidateNames.length > 1) {
		Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);
		for (String beanName : candidateNames) {
			if (containsSingleton(beanName) && args == null) {
				Object beanInstance = getBean(beanName);
				candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
			}
			else {
				candidates.put(beanName, getType(beanName));
			}
		}
		String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
		if (candidateName == null) {
			candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
		}
		if (candidateName != null) {
			Object beanInstance = candidates.get(candidateName);
			if (beanInstance == null || beanInstance instanceof Class) {
				beanInstance = getBean(candidateName, requiredType.toClass(), args);
			}
			return new NamedBeanHolder<>(candidateName, (T) beanInstance);
		}
		if (!nonUniqueAsNull) {
			throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
		}
	}

	return null;
}

@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
	if (Optional.class == descriptor.getDependencyType()) {
		return createOptionalDependency(descriptor, requestingBeanName);
	}
	else if (ObjectFactory.class == descriptor.getDependencyType() ||
			ObjectProvider.class == descriptor.getDependencyType()) {
		return new DependencyObjectProvider(descriptor, requestingBeanName);
	}
	else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
		return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
	}
	else {
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
	}
}

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
	try {
		Object shortcut = descriptor.resolveShortcut(this);
		if (shortcut != null) {
			return shortcut;
		}

		Class<?> type = descriptor.getDependencyType();
		Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
		if (value != null) {
			if (value instanceof String) {
				String strVal = resolveEmbeddedValue((String) value);
				BeanDefinition bd = (beanName != null && containsBean(beanName) ?
						getMergedBeanDefinition(beanName) : null);
				value = evaluateBeanDefinitionString(strVal, bd);
			}
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
			try {
				return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
			}
			catch (UnsupportedOperationException ex) {
				// A custom TypeConverter which does not support TypeDescriptor resolution...
				return (descriptor.getField() != null ?
						converter.convertIfNecessary(value, type, descriptor.getField()) :
						converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
			}
		}

		Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
		if (multipleBeans != null) {
			return multipleBeans;
		}

		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (matchingBeans.isEmpty()) {
			if (isRequired(descriptor)) {
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			return null;
		}

		String autowiredBeanName;
		Object instanceCandidate;

		if (matchingBeans.size() > 1) {
			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
			if (autowiredBeanName == null) {
				if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
					return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
				}
				else {
					// In case of an optional Collection/Map, silently ignore a non-unique case:
					// possibly it was meant to be an empty collection of multiple regular beans
					// (before 4.3 in particular when we didn't even look for collection beans).
					return null;
				}
			}
			instanceCandidate = matchingBeans.get(autowiredBeanName);
		}
		else {
			// We have exactly one match.
			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
			autowiredBeanName = entry.getKey();
			instanceCandidate = entry.getValue();
		}

		if (autowiredBeanNames != null) {
			autowiredBeanNames.add(autowiredBeanName);
		}
		if (instanceCandidate instanceof Class) {
			instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
		}
		Object result = instanceCandidate;
		if (result instanceof NullBean) {
			if (isRequired(descriptor)) {
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			result = null;
		}
		if (!ClassUtils.isAssignableValue(type, result)) {
			throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
		}
		return result;
	}
	finally {
		ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
	}
}

@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {

	final Class<?> type = descriptor.getDependencyType();

	if (descriptor instanceof StreamDependencyDescriptor) {
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		Stream<Object> stream = matchingBeans.keySet().stream()
				.map(name -> descriptor.resolveCandidate(name, type, this))
				.filter(bean -> !(bean instanceof NullBean));
		if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
			stream = stream.sorted(adaptOrderComparator(matchingBeans));
		}
		return stream;
	}
	else if (type.isArray()) {
		Class<?> componentType = type.getComponentType();
		ResolvableType resolvableType = descriptor.getResolvableType();
		Class<?> resolvedArrayType = resolvableType.resolve(type);
		if (resolvedArrayType != type) {
			componentType = resolvableType.getComponentType().resolve();
		}
		if (componentType == null) {
			return null;
		}
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
		Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
		if (result instanceof Object[]) {
			Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
			if (comparator != null) {
				Arrays.sort((Object[]) result, comparator);
			}
		}
		return result;
	}
	else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
		Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
		if (elementType == null) {
			return null;
		}
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
		Object result = converter.convertIfNecessary(matchingBeans.values(), type);
		if (result instanceof List) {
			Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
			if (comparator != null) {
				((List<?>) result).sort(comparator);
			}
		}
		return result;
	}
	else if (Map.class == type) {
		ResolvableType mapType = descriptor.getResolvableType().asMap();
		Class<?> keyType = mapType.resolveGeneric(0);
		if (String.class != keyType) {
			return null;
		}
		Class<?> valueType = mapType.resolveGeneric(1);
		if (valueType == null) {
			return null;
		}
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		return matchingBeans;
	}
	else {
		return null;
	}
}

private boolean isRequired(DependencyDescriptor descriptor) {
	return getAutowireCandidateResolver().isRequired(descriptor);
}

private boolean indicatesMultipleBeans(Class<?> type) {
	return (type.isArray() || (type.isInterface() &&
			(Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type))));
}

@Nullable
private Comparator<Object> adaptDependencyComparator(Map<String, ?> matchingBeans) {
	Comparator<Object> comparator = getDependencyComparator();
	if (comparator instanceof OrderComparator) {
		return ((OrderComparator) comparator).withSourceProvider(
				createFactoryAwareOrderSourceProvider(matchingBeans));
	}
	else {
		return comparator;
	}
}

private Comparator<Object> adaptOrderComparator(Map<String, ?> matchingBeans) {
	Comparator<Object> dependencyComparator = getDependencyComparator();
	OrderComparator comparator = (dependencyComparator instanceof OrderComparator ?
			(OrderComparator) dependencyComparator : OrderComparator.INSTANCE);
	return comparator.withSourceProvider(createFactoryAwareOrderSourceProvider(matchingBeans));
}

private OrderComparator.OrderSourceProvider createFactoryAwareOrderSourceProvider(Map<String, ?> beans) {
	IdentityHashMap<Object, String> instancesToBeanNames = new IdentityHashMap<>();
	beans.forEach((beanName, instance) -> instancesToBeanNames.put(instance, beanName));
	return new FactoryAwareOrderSourceProvider(instancesToBeanNames);
}

/**
 * Find bean instances that match the required type.
 * Called during autowiring for the specified bean.
 * @param beanName the name of the bean that is about to be wired
 * @param requiredType the actual type of bean to look for
 * (may be an array component type or collection element type)
 * @param descriptor the descriptor of the dependency to resolve
 * @return a Map of candidate names and candidate instances that match
 * the required type (never {@code null})
 * @throws BeansException in case of errors
 * @see #autowireByType
 * @see #autowireConstructor
 */
protected Map<String, Object> findAutowireCandidates(
		@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {

	String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
			this, requiredType, true, descriptor.isEager());
	Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
	for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
		Class<?> autowiringType = classObjectEntry.getKey();
		if (autowiringType.isAssignableFrom(requiredType)) {
			Object autowiringValue = classObjectEntry.getValue();
			autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
			if (requiredType.isInstance(autowiringValue)) {
				result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
				break;
			}
		}
	}
	for (String candidate : candidateNames) {
		if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
			addCandidateEntry(result, candidate, descriptor, requiredType);
		}
	}
	if (result.isEmpty()) {
		boolean multiple = indicatesMultipleBeans(requiredType);
		// Consider fallback matches if the first pass failed to find anything...
		DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
		for (String candidate : candidateNames) {
			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
					(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
				addCandidateEntry(result, candidate, descriptor, requiredType);
			}
		}
		if (result.isEmpty() && !multiple) {
			// Consider self references as a final pass...
			// but in the case of a dependency collection, not the very same bean itself.
			for (String candidate : candidateNames) {
				if (isSelfReference(beanName, candidate) &&
						(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
						isAutowireCandidate(candidate, fallbackDescriptor)) {
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}
		}
	}
	return result;
}

/**
 * Add an entry to the candidate map: a bean instance if available or just the resolved
 * type, preventing early bean initialization ahead of primary candidate selection.
 */
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
		DependencyDescriptor descriptor, Class<?> requiredType) {

	if (descriptor instanceof MultiElementDescriptor) {
		Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
		if (!(beanInstance instanceof NullBean)) {
			candidates.put(candidateName, beanInstance);
		}
	}
	else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor &&
			((StreamDependencyDescriptor) descriptor).isOrdered())) {
		Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
		candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
	}
	else {
		candidates.put(candidateName, getType(candidateName));
	}
}

/**
 * Determine the autowire candidate in the given set of beans.
 * <p>Looks for {@code @Primary} and {@code @Priority} (in that order).
 * @param candidates a Map of candidate names and candidate instances
 * that match the required type, as returned by {@link #findAutowireCandidates}
 * @param descriptor the target dependency to match against
 * @return the name of the autowire candidate, or {@code null} if none found
 */
@Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
	Class<?> requiredType = descriptor.getDependencyType();
	String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
	if (primaryCandidate != null) {
		return primaryCandidate;
	}
	String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
	if (priorityCandidate != null) {
		return priorityCandidate;
	}
	// Fallback
	for (Map.Entry<String, Object> entry : candidates.entrySet()) {
		String candidateName = entry.getKey();
		Object beanInstance = entry.getValue();
		if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
				matchesBeanName(candidateName, descriptor.getDependencyName())) {
			return candidateName;
		}
	}
	return null;
}

/**
 * Determine the primary candidate in the given set of beans.
 * @param candidates a Map of candidate names and candidate instances
 * (or candidate classes if not created yet) that match the required type
 * @param requiredType the target dependency type to match against
 * @return the name of the primary candidate, or {@code null} if none found
 * @see #isPrimary(String, Object)
 */
@Nullable
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
	String primaryBeanName = null;
	for (Map.Entry<String, Object> entry : candidates.entrySet()) {
		String candidateBeanName = entry.getKey();
		Object beanInstance = entry.getValue();
		if (isPrimary(candidateBeanName, beanInstance)) {
			if (primaryBeanName != null) {
				boolean candidateLocal = containsBeanDefinition(candidateBeanName);
				boolean primaryLocal = containsBeanDefinition(primaryBeanName);
				if (candidateLocal && primaryLocal) {
					throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
							"more than one 'primary' bean found among candidates: " + candidates.keySet());
				}
				else if (candidateLocal) {
					primaryBeanName = candidateBeanName;
				}
			}
			else {
				primaryBeanName = candidateBeanName;
			}
		}
	}
	return primaryBeanName;
}

/**
 * Determine the candidate with the highest priority in the given set of beans.
 * <p>Based on {@code @javax.annotation.Priority}. As defined by the related
 * {@link org.springframework.core.Ordered} interface, the lowest value has
 * the highest priority.
 * @param candidates a Map of candidate names and candidate instances
 * (or candidate classes if not created yet) that match the required type
 * @param requiredType the target dependency type to match against
 * @return the name of the candidate with the highest priority,
 * or {@code null} if none found
 * @see #getPriority(Object)
 */
@Nullable
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
	String highestPriorityBeanName = null;
	Integer highestPriority = null;
	for (Map.Entry<String, Object> entry : candidates.entrySet()) {
		String candidateBeanName = entry.getKey();
		Object beanInstance = entry.getValue();
		if (beanInstance != null) {
			Integer candidatePriority = getPriority(beanInstance);
			if (candidatePriority != null) {
				if (highestPriorityBeanName != null) {
					if (candidatePriority.equals(highestPriority)) {
						throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
								"Multiple beans found with the same priority ('" + highestPriority +
								"') among candidates: " + candidates.keySet());
					}
					else if (candidatePriority < highestPriority) {
						highestPriorityBeanName = candidateBeanName;
						highestPriority = candidatePriority;
					}
				}
				else {
					highestPriorityBeanName = candidateBeanName;
					highestPriority = candidatePriority;
				}
			}
		}
	}
	return highestPriorityBeanName;
}

/**
 * Return whether the bean definition for the given bean name has been
 * marked as a primary bean.
 * @param beanName the name of the bean
 * @param beanInstance the corresponding bean instance (can be null)
 * @return whether the given bean qualifies as primary
 */
protected boolean isPrimary(String beanName, Object beanInstance) {
	if (containsBeanDefinition(beanName)) {
		return getMergedLocalBeanDefinition(beanName).isPrimary();
	}
	BeanFactory parent = getParentBeanFactory();
	return (parent instanceof DefaultListableBeanFactory &&
			((DefaultListableBeanFactory) parent).isPrimary(beanName, beanInstance));
}

/**
 * Return the priority assigned for the given bean instance by
 * the {@code javax.annotation.Priority} annotation.
 * <p>The default implementation delegates to the specified
 * {@link #setDependencyComparator dependency comparator}, checking its
 * {@link OrderComparator#getPriority method} if it is an extension of
 * Spring's common {@link OrderComparator} - typically, an
 * {@link org.springframework.core.annotation.AnnotationAwareOrderComparator}.
 * If no such comparator is present, this implementation returns {@code null}.
 * @param beanInstance the bean instance to check (can be {@code null})
 * @return the priority assigned to that bean or {@code null} if none is set
 */
@Nullable
protected Integer getPriority(Object beanInstance) {
	Comparator<Object> comparator = getDependencyComparator();
	if (comparator instanceof OrderComparator) {
		return ((OrderComparator) comparator).getPriority(beanInstance);
	}
	return null;
}

/**
 * Determine whether the given candidate name matches the bean name or the aliases
 * stored in this bean definition.
 */
protected boolean matchesBeanName(String beanName, @Nullable String candidateName) {
	return (candidateName != null &&
			(candidateName.equals(beanName) || ObjectUtils.containsElement(getAliases(beanName), candidateName)));
}

/**
 * Determine whether the given beanName/candidateName pair indicates a self reference,
 * i.e. whether the candidate points back to the original bean or to a factory method
 * on the original bean.
 */
private boolean isSelfReference(@Nullable String beanName, @Nullable String candidateName) {
	return (beanName != null && candidateName != null &&
			(beanName.equals(candidateName) || (containsBeanDefinition(candidateName) &&
					beanName.equals(getMergedLocalBeanDefinition(candidateName).getFactoryBeanName()))));
}

/**
 * Raise a NoSuchBeanDefinitionException or BeanNotOfRequiredTypeException
 * for an unresolvable dependency.
 */
private void raiseNoMatchingBeanFound(
		Class<?> type, ResolvableType resolvableType, DependencyDescriptor descriptor) throws BeansException {

	checkBeanNotOfRequiredType(type, descriptor);

	throw new NoSuchBeanDefinitionException(resolvableType,
			"expected at least 1 bean which qualifies as autowire candidate. " +
			"Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations()));
}

/**
 * Raise a BeanNotOfRequiredTypeException for an unresolvable dependency, if applicable,
 * i.e. if the target type of the bean would match but an exposed proxy doesn't.
 */
private void checkBeanNotOfRequiredType(Class<?> type, DependencyDescriptor descriptor) {
	for (String beanName : this.beanDefinitionNames) {
		RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
		Class<?> targetType = mbd.getTargetType();
		if (targetType != null && type.isAssignableFrom(targetType) &&
				isAutowireCandidate(beanName, mbd, descriptor, getAutowireCandidateResolver())) {
			// Probably a proxy interfering with target type match -> throw meaningful exception.
			Object beanInstance = getSingleton(beanName, false);
			Class<?> beanType = (beanInstance != null && beanInstance.getClass() != NullBean.class ?
					beanInstance.getClass() : predictBeanType(beanName, mbd));
			if (beanType != null && !type.isAssignableFrom(beanType)) {
				throw new BeanNotOfRequiredTypeException(beanName, type, beanType);
			}
		}
	}

	BeanFactory parent = getParentBeanFactory();
	if (parent instanceof DefaultListableBeanFactory) {
		((DefaultListableBeanFactory) parent).checkBeanNotOfRequiredType(type, descriptor);
	}
}

/**
 * Create an {@link Optional} wrapper for the specified dependency.
 */
private Optional<?> createOptionalDependency(
		DependencyDescriptor descriptor, @Nullable String beanName, final Object... args) {

	DependencyDescriptor descriptorToUse = new NestedDependencyDescriptor(descriptor) {
		@Override
		public boolean isRequired() {
			return false;
		}
		@Override
		public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
			return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :
					super.resolveCandidate(beanName, requiredType, beanFactory));
		}
	};
	Object result = doResolveDependency(descriptorToUse, beanName, null, null);
	return (result instanceof Optional ? (Optional<?>) result : Optional.ofNullable(result));
}


@Override
public String toString() {
	StringBuilder sb = new StringBuilder(ObjectUtils.identityToString(this));
	sb.append(": defining beans [");
	sb.append(StringUtils.collectionToCommaDelimitedString(this.beanDefinitionNames));
	sb.append("]; ");
	BeanFactory parent = getParentBeanFactory();
	if (parent == null) {
		sb.append("root of factory hierarchy");
	}
	else {
		sb.append("parent: ").append(ObjectUtils.identityToString(parent));
	}
	return sb.toString();
}


//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------

private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
	throw new NotSerializableException("DefaultListableBeanFactory itself is not deserializable - " +
			"just a SerializedBeanFactoryReference is");
}

protected Object writeReplace() throws ObjectStreamException {
	if (this.serializationId != null) {
		return new SerializedBeanFactoryReference(this.serializationId);
	}
	else {
		throw new NotSerializableException("DefaultListableBeanFactory has no serialization id");
	}
}


/**
 * Minimal id reference to the factory.
 * Resolved to the actual factory instance on deserialization.
 */
private static class SerializedBeanFactoryReference implements Serializable {

	private final String id;

	public SerializedBeanFactoryReference(String id) {
		this.id = id;
	}

	private Object readResolve() {
		Reference<?> ref = serializableFactories.get(this.id);
		if (ref != null) {
			Object result = ref.get();
			if (result != null) {
				return result;
			}
		}
		// Lenient fallback: dummy factory in case of original factory not found...
		DefaultListableBeanFactory dummyFactory = new DefaultListableBeanFactory();
		dummyFactory.serializationId = this.id;
		return dummyFactory;
	}
}


/**
 * A dependency descriptor marker for nested elements.
 */
private static class NestedDependencyDescriptor extends DependencyDescriptor {

	public NestedDependencyDescriptor(DependencyDescriptor original) {
		super(original);
		increaseNestingLevel();
	}
}


/**
 * A dependency descriptor for a multi-element declaration with nested elements.
 */
private static class MultiElementDescriptor extends NestedDependencyDescriptor {

	public MultiElementDescriptor(DependencyDescriptor original) {
		super(original);
	}
}


/**
 * A dependency descriptor marker for stream access to multiple elements.
 */
private static class StreamDependencyDescriptor extends DependencyDescriptor {

	private final boolean ordered;

	public StreamDependencyDescriptor(DependencyDescriptor original, boolean ordered) {
		super(original);
		this.ordered = ordered;
	}

	public boolean isOrdered() {
		return this.ordered;
	}
}


private interface BeanObjectProvider<T> extends ObjectProvider<T>, Serializable {
}


/**
 * Serializable ObjectFactory/ObjectProvider for lazy resolution of a dependency.
 */
private class DependencyObjectProvider implements BeanObjectProvider<Object> {

	private final DependencyDescriptor descriptor;

	private final boolean optional;

	@Nullable
	private final String beanName;

	public DependencyObjectProvider(DependencyDescriptor descriptor, @Nullable String beanName) {
		this.descriptor = new NestedDependencyDescriptor(descriptor);
		this.optional = (this.descriptor.getDependencyType() == Optional.class);
		this.beanName = beanName;
	}

	@Override
	public Object getObject() throws BeansException {
		if (this.optional) {
			return createOptionalDependency(this.descriptor, this.beanName);
		}
		else {
			Object result = doResolveDependency(this.descriptor, this.beanName, null, null);
			if (result == null) {
				throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType());
			}
			return result;
		}
	}

	@Override
	public Object getObject(final Object... args) throws BeansException {
		if (this.optional) {
			return createOptionalDependency(this.descriptor, this.beanName, args);
		}
		else {
			DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
				@Override
				public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
					return beanFactory.getBean(beanName, args);
				}
			};
			Object result = doResolveDependency(descriptorToUse, this.beanName, null, null);
			if (result == null) {
				throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType());
			}
			return result;
		}
	}

	@Override
	@Nullable
	public Object getIfAvailable() throws BeansException {
		if (this.optional) {
			return createOptionalDependency(this.descriptor, this.beanName);
		}
		else {
			DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
				@Override
				public boolean isRequired() {
					return false;
				}
			};
			return doResolveDependency(descriptorToUse, this.beanName, null, null);
		}
	}

	@Override
	@Nullable
	public Object getIfUnique() throws BeansException {
		DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
			@Override
			public boolean isRequired() {
				return false;
			}
			@Override
			@Nullable
			public Object resolveNotUnique(ResolvableType type, Map<String, Object> matchingBeans) {
				return null;
			}
		};
		if (this.optional) {
			return createOptionalDependency(descriptorToUse, this.beanName);
		}
		else {
			return doResolveDependency(descriptorToUse, this.beanName, null, null);
		}
	}

	@Nullable
	protected Object getValue() throws BeansException {
		if (this.optional) {
			return createOptionalDependency(this.descriptor, this.beanName);
		}
		else {
			return doResolveDependency(this.descriptor, this.beanName, null, null);
		}
	}

	@Override
	public Stream<Object> stream() {
		return resolveStream(false);
	}

	@Override
	public Stream<Object> orderedStream() {
		return resolveStream(true);
	}

	@SuppressWarnings("unchecked")
	private Stream<Object> resolveStream(boolean ordered) {
		DependencyDescriptor descriptorToUse = new StreamDependencyDescriptor(this.descriptor, ordered);
		Object result = doResolveDependency(descriptorToUse, this.beanName, null, null);
		return (result instanceof Stream ? (Stream<Object>) result : Stream.of(result));
	}
}


/**
 * Separate inner class for avoiding a hard dependency on the {@code javax.inject} API.
 * Actual {@code javax.inject.Provider} implementation is nested here in order to make it
 * invisible for Graal's introspection of DefaultListableBeanFactory's nested classes.
 */
private class Jsr330Factory implements Serializable {

	public Object createDependencyProvider(DependencyDescriptor descriptor, @Nullable String beanName) {
		return new Jsr330Provider(descriptor, beanName);
	}

	private class Jsr330Provider extends DependencyObjectProvider implements Provider<Object> {

		public Jsr330Provider(DependencyDescriptor descriptor, @Nullable String beanName) {
			super(descriptor, beanName);
		}

		@Override
		@Nullable
		public Object get() throws BeansException {
			return getValue();
		}
	}
}


/**
 * An {@link org.springframework.core.OrderComparator.OrderSourceProvider} implementation
 * that is aware of the bean metadata of the instances to sort.
 * <p>Lookup for the method factory of an instance to sort, if any, and let the
 * comparator retrieve the {@link org.springframework.core.annotation.Order}
 * value defined on it. This essentially allows for the following construct:
 */
private class FactoryAwareOrderSourceProvider implements OrderComparator.OrderSourceProvider {

	private final Map<Object, String> instancesToBeanNames;

	public FactoryAwareOrderSourceProvider(Map<Object, String> instancesToBeanNames) {
		this.instancesToBeanNames = instancesToBeanNames;
	}
m4
@Override @Nullable public Object getOrderSource(Object obj) { RootBeanDefinition beanDefinition = getRootBeanDefinition(this.instancesToBeanNames.get(obj)); if (beanDefinition == null) { return null; } List sources = new ArrayList<>(2); Method factoryMethod = beanDefinition.getResolvedFactoryMethod(); if (factoryMethod != null) { sources.add(factoryMethod); } Class<?> targetType = beanDefinition.getTargetType(); if (targetType != null && targetType != obj.getClass()) { sources.add(targetType); } return sources.toArray(); }
	@Nullable
	private RootBeanDefinition getRootBeanDefinition(@Nullable String beanName) {
		if (beanName != null && containsBeanDefinition(beanName)) {
			BeanDefinition bd = getMergedBeanDefinition(beanName);
			if (bd instanceof RootBeanDefinition) {
				return (RootBeanDefinition) bd;
			}
		}
		return null;
	}
}

}

id=a
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java硕哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值