Spring Bean 生命周期
[TOC]
Chapter 1 Spring BeanDefinition 配置阶段
1 通过 XML 的方式配置 BeanDefinition
通过 XML 方式配置并读取 Bean 元信息配置示例
package com.geekbang.thinking.in.spring.bean.lifecycle;
import com.geekbang.spring.ioc.container.overview.domain.User;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
/**
* @ClassName BeanMetadataConfigurationDemo
* @Description 通过 XML 方式配置并读取 Bean 元信息配置示例
* @Author WQ
* @Date 2022/8/10 16:01
* @Version 1.0
*/
public class BeanMetadataConfigurationByXmlDemo {
public static void main(String[] args) {
// 创建默认的 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 创建 XML 的 Bean 定义读取器
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
// XML 文件位置
String location = "META-INF/bean-definition-user.xml";
// 读取器根据文件位置去加载 Bean 定义
reader.loadBeanDefinitions(location);
// 依赖查找 User 对象
User user = beanFactory.getBean("user", User.class);
System.out.println(user);
}
}
2 通过 Properties 方式配置并读取 Bean 元信息配置
通过 Properties 方式配置并读取 BeanDefinition 示例
package com.geekbang.thinking.in.spring.bean.lifecycle;
import com.geekbang.spring.ioc.container.overview.domain.User;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
/**
* @ClassName BeanMetadataConfigurationByPropertiesDemo
* @Description 通过 Properties 方式配置并读取 Bean 元信息配置示例
* @Author WQ
* @Date 2022/8/10 16:01
* @Version 1.0
*/
public class BeanMetadataConfigurationByPropertiesDemo {
public static void main(String[] args) {
// 创建默认的 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 创建 Properties 的 Bean 定义读取器
PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(beanFactory);
// Properties 文件位置 (文件编码为:UTF-8)
String location = "META-INF/bean-definition-user.properties";
// 将 Properties 配置文件读取到 Resource
Resource classPathResource = new ClassPathResource(location);
// 转化为编码的 Resource
EncodedResource encodedResource = new EncodedResource(classPathResource, "UTF-8");
// 读取 Resource 加载 bean 的元配置
reader.loadBeanDefinitions(encodedResource);
// 通过依赖查找获取 User 对象
User user = beanFactory.getBean("user", User.class);
System.out.println(user);
}
}
3 通过 AnnotatedBeanDefinitionReader 解析 beanDefinition
package com.geekbang.thinking.in.spring.bean.lifecycle;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
/**
* @ClassName AnnotatedBeanDefinitionParsingDemo
* @Description 面向注解 BeanDefinition 解析
* @Author WQ
* @Date 2022/8/10 17:42
* @Version 1.0
*/
public class AnnotatedBeanDefinitionParsingDemo {
public static void main(String[] args) {
// 创建 BeanFactory 实例
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 创建 AnnotatedBeanDefinitionReader 注解读取器
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(beanFactory);
// 获取注册前的 beanDefinition 数量
int beanDefinitionCountBeforeRegister = beanFactory.getBeanDefinitionCount();
// 将当前类注册到容器中
reader.register(AnnotatedBeanDefinitionParsingDemo.class);
// 获取注册后的 beanDefinition 数量
int beanDefinitionCountAfterRegister = beanFactory.getBeanDefinitionCount();
System.out.println("已加载的 BeanDefinition counts: " + (beanDefinitionCountAfterRegister - beanDefinitionCountBeforeRegister));
// 普通的 Class 作为 Component 注册到 Spring IoC 容器后,通常 Bean 名称为 annotatedBeanDefinitionParsingDemo
// Bean 名称生成来自于 BeanNameGenerator,注解实现 AnnotationBeanNameGenerator
AnnotatedBeanDefinitionParsingDemo demo = beanFactory.getBean("annotatedBeanDefinitionParsingDemo",
AnnotatedBeanDefinitionParsingDemo.class);
System.out.println(demo);
}
}
Chapter 2 Spring BeanDefinition 注册阶段
1 BeanDefinitionRegistry 接口分析
AliasRegistry 是一个别名注册,里面没有涉及到注册相关的事件,BeanDefinitionRegistry 即是顶层接口。 BeanDefinitionRegistry 中定义的方法为对 BeanDefinition 的增删改查。
BeanDefinitionRegistry 的实现类为 DefaultListableBeanFactory。
public interface BeanDefinitionRegistry extends AliasRegistry {
/**
* 注册 BeanDefinition
* Register a new bean definition with this registry.
* Must support RootBeanDefinition and ChildBeanDefinition.
* @param beanName the name of the bean instance to register
* @param beanDefinition definition of the bean instance to register
* @throws BeanDefinitionStoreException if the BeanDefinition is invalid
* @throws BeanDefinitionOverrideException if there is already a BeanDefinition
* for the specified bean name and we are not allowed to override it
* @see GenericBeanDefinition
* @see RootBeanDefinition
* @see ChildBeanDefinition
*/
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
/**
* 移除 BeanDefinition
* Remove the BeanDefinition for the given name.
* @param beanName the name of the bean instance to register
* @throws NoSuchBeanDefinitionException if there is no such bean definition
*/
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
/**
* 获取 BeanDefinition
* Return the BeanDefinition for the given bean name.
* @param beanName name of the bean to find a definition for
* @return the BeanDefinition for the given name (never {@code null})
* @throws NoSuchBeanDefinitionException if there is no such bean definition
*/
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
/**
* 是否包含 BeanDefinition
* Check if this registry contains a bean definition with the given name.
* @param beanName the name of the bean to look for
* @return if this registry contains a bean definition with the given name
*/
boolean containsBeanDefinition(String beanName);
/**
* 获取 BeanDefinition 的名称列表
* Return the names of all beans defined in this registry.
* @return the names of all beans defined in this registry,
* or an empty array if none defined
*/
String[] getBeanDefinitionNames();
/**
* 获取 BeanDefinition 的数量
* Return the number of beans defined in the registry.
* @return the number of beans defined in the registry
*/
int getBeanDefinitionCount();
/**
* Determine whether the given bean name is already in use within this registry,
* i.e. whether there is a local bean or alias registered under this name.
* @param beanName the name to check
* @return whether the given bean name is already in use
*/
boolean isBeanNameInUse(String beanName);
}
2 DefaultListableBeanFactory#registerBeanDefinition
DefaultListableBeanFactory 中重写 BeanDefinitionRegistry 的注册方法。
- String beanName Bean 的名称
- BeanDefinition beanDefinition 需要注册的 Bean 的元信息 该方法有个注意事项: beanDefinitionMap 用于 beanDefinition 的存储与查找,而 beanDefinitionNames 用于记录 beanDefinition 的注册顺序。
/** bean 定义对象的映射,以 bean 名称为键。 */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** bean 定义名称列表,按注册顺序排列。 */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// 参数检测,对 Bean 名称以及 beanDefinition 进行非空判断
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// 如果是 AbstractBeanDefinition 的实例
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
// 进行 beanDefinition 校验
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 从缓存中获取 BeanDefinition
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
// 缓存中根据 beanName 获取到存在的 BeanDefinition
if (existingDefinition != null) {
// isAllowBeanDefinitionOverriding() 方法返回是否允许覆盖 beanDefinition
if (!isAllowBeanDefinitionOverriding()) {
// 不允许覆盖,则抛出 BeanDefinition 覆盖异常
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// 当 beanDefinition 的角色从 ROLE_APPLICATION 变更为 ROLE_SUPPORT、ROLE_INFRASTRUCTURE 打印日志
// 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)) {
// 覆盖前后的 beanDefinition 不一致时,进行日志打印,这里是进行 DEBUG 级别的日志打印,普通情况下看不到
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 + "]");
}
}
// 覆盖当前的 beanName 对应的 beanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else { // 缓存中根据 beanName 没有获取到 BeanDefinition
if (hasBeanCreationStarted()) {
// 检测工厂的 bean 已经开始创建,一般情况下为false
// 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);
// 添加到 beanDefinitionNames 这个 ArrayList 中,用于 bean 的注册顺序控制
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// 检测工厂的 bean 还未创建
// 仍处于启动注册阶段
// 添加到缓存中
this.beanDefinitionMap.put(beanName, beanDefinition);
// 添加到 beanDefinition 名称列表中
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
Chapter 3 Spring BeanDefinition 合并阶段
1 RootBeanDefinition
根节点的 BeanDefinition 该 BeanDefinition 存在以下特征:
- 不可设置 parent 节点 setParentName()方法会抛出异常
- RootBeanDefinition 是最顶层节点 示例 Bean: User
/*
* 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
*
* 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 org.springframework.beans.factory.support;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* A root bean definition represents the merged bean definition that backs
* a specific bean in a Spring BeanFactory at runtime. It might have been created
* from multiple original bean definitions that inherit from each other,
* typically registered as {@link GenericBeanDefinition GenericBeanDefinitions}.
* A root bean definition is essentially the 'unified' bean definition view at runtime.
*
* <p>Root bean definitions may also be used for registering individual bean definitions
* in the configuration phase. However, since Spring 2.5, the preferred way to register
* bean definitions programmatically is the {@link GenericBeanDefinition} class.
* GenericBeanDefinition has the advantage that it allows to dynamically define
* parent dependencies, not 'hard-coding' the role as a root bean definition.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see GenericBeanDefinition
* @see ChildBeanDefinition
*/
@SuppressWarnings("serial")
public class RootBeanDefinition extends AbstractBeanDefinition {
@Nullable
private BeanDefinitionHolder decoratedDefinition;
@Nullable
private AnnotatedElement qualifiedElement;
/** Determines if the definition needs to be re-merged. */
volatile boolean stale;
boolean allowCaching = true;
boolean isFactoryMethodUnique = false;
@Nullable
volatile ResolvableType targetType;
/** Package-visible field for caching the determined Class of a given bean definition. */
@Nullable
volatile Class<?> resolvedTargetType;
/** Package-visible field for caching if the bean is a factory bean. */
@Nullable
volatile Boolean isFactoryBean;
/** Package-visible field for caching the return type of a generically typed factory method. */
@Nullable
volatile ResolvableType factoryMethodReturnType;
/** Package-visible field for caching a unique factory method candidate for introspection. */
@Nullable
volatile Method factoryMethodToIntrospect;
/** Common lock for the four constructor fields below. */
final Object constructorArgumentLock = new Object();
/** Package-visible field for caching the resolved constructor or factory method. */
@Nullable
Executable resolvedConstructorOrFactoryMethod;
/** Package-visible field that marks the constructor arguments as resolved. */
boolean constructorArgumentsResolved = false;
/** Package-visible field for caching fully resolved constructor arguments. */
@Nullable
Object[] resolvedConstructorArguments;
/** Package-visible field for caching partly prepared constructor arguments. */
@Nullable
Object[] preparedConstructorArguments;
/** Common lock for the two post-processing fields below. */
final Object postProcessingLock = new Object();
/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied. */
boolean postProcessed = false;
/** Package-visible field that indicates a before-instantiation post-processor having kicked in. */
@Nullable
volatile Boolean beforeInstantiationResolved;
@Nullable
private Set<Member> externallyManagedConfigMembers;
@Nullable
private Set<String> externallyManagedInitMethods;
@Nullable
private Set<String> externallyManagedDestroyMethods;
/**
* Create a new RootBeanDefinition, to be configured through its bean
* properties and configuration methods.
* @see #setBeanClass
* @see #setScope
* @see #setConstructorArgumentValues
* @see #setPropertyValues
*/
public RootBeanDefinition() {
super();
}
/**
* Create a new RootBeanDefinition for a singleton.
* @param beanClass the class of the bean to instantiate
* @see #setBeanClass
*/
public RootBeanDefinition(@Nullable Class<?> beanClass) {
super();
setBeanClass(beanClass);
}
/**
* Create a new RootBeanDefinition for a singleton bean, constructing each instance
* through calling the given supplier (possibly a lambda or method reference).
* @param beanClass the class of the bean to instantiate
* @param instanceSupplier the supplier to construct a bean instance,
* as an alternative to a declaratively specified factory method
* @since 5.0
* @see #setInstanceSupplier
*/
public <T> RootBeanDefinition(@Nullable Class<T> beanClass, @Nullable Supplier<T> instanceSupplier) {
super();
setBeanClass(beanClass);
setInstanceSupplier(instanceSupplier);
}
/**
* Create a new RootBeanDefinition for a scoped bean, constructing each instance
* through calling the given supplier (possibly a lambda or method reference).
* @param beanClass the class of the bean to instantiate
* @param scope the name of the corresponding scope
* @param instanceSupplier the supplier to construct a bean instance,
* as an alternative to a declaratively specified factory method
* @since 5.0
* @see #setInstanceSupplier
*/
public <T> RootBeanDefinition(@Nullable Class<T> beanClass, String scope, @Nullable Supplier<T> instanceSupplier) {
super();
setBeanClass(beanClass);
setScope(scope);
setInstanceSupplier(instanceSupplier);
}
/**
* Create a new RootBeanDefinition for a singleton,
* using the given autowire mode.
* @param beanClass the class of the bean to instantiate
* @param autowireMode by name or type, using the constants in this interface
* @param dependencyCheck whether to perform a dependency check for objects
* (not applicable to autowiring a constructor, thus ignored there)
*/
public RootBeanDefinition(@Nullable Class<?> beanClass, int autowireMode, boolean dependencyCheck) {
super();
setBeanClass(beanClass);
setAutowireMode(autowireMode);
if (dependencyCheck && getResolvedAutowireMode() != AUTOWIRE_CONSTRUCTOR) {
setDependencyCheck(DEPENDENCY_CHECK_OBJECTS);
}
}
/**
* Create a new RootBeanDefinition for a singleton,
* providing constructor arguments and property values.
* @param beanClass the class of the bean to instantiate
* @param cargs the constructor argument values to apply
* @param pvs the property values to apply
*/
public RootBeanDefinition(@Nullable Class<?> beanClass, @Nullable ConstructorArgumentValues cargs,
@Nullable MutablePropertyValues pvs) {
super(cargs, pvs);
setBeanClass(beanClass);
}
/**
* Create a new RootBeanDefinition for a singleton,
* providing constructor arguments and property values.
* <p>Takes a bean class name to avoid eager loading of the bean class.
* @param beanClassName the name of the class to instantiate
*/
public RootBeanDefinition(String beanClassName) {
setBeanClassName(beanClassName);
}
/**
* Create a new RootBeanDefinition for a singleton,
* providing constructor arguments and property values.
* <p>Takes a bean class name to avoid eager loading of the bean class.
* @param beanClassName the name of the class to instantiate
* @param cargs the constructor argument values to apply
* @param pvs the property values to apply
*/
public RootBeanDefinition(String beanClassName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
super(cargs, pvs);
setBeanClassName(beanClassName);
}
/**
* Create a new RootBeanDefinition as deep copy of the given
* bean definition.
* @param original the original bean definition to copy from
*/
public RootBeanDefinition(RootBeanDefinition original) {
super(original);
this.decoratedDefinition = original.decoratedDefinition;
this.qualifiedElement = original.qualifiedElement;
this.allowCaching = original.allowCaching;
this.isFactoryMethodUnique = original.isFactoryMethodUnique;
this.targetType = original.targetType;
this.factoryMethodToIntrospect = original.factoryMethodToIntrospect;
}
/**
* Create a new RootBeanDefinition as deep copy of the given
* bean definition.
* @param original the original bean definition to copy from
*/
RootBeanDefinition(BeanDefinition original) {
super(original);
}
@Override
public String getParentName() {
return null;
}
@Override
public void setParentName(@Nullable String parentName) {
if (parentName != null) {
throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference");
}
}
/**
* Register a target definition that is being decorated by this bean definition.
*/
public void setDecoratedDefinition(@Nullable BeanDefinitionHolder decoratedDefinition) {
this.decoratedDefinition = decoratedDefinition;
}
/**
* Return the target definition that is being decorated by this bean definition, if any.
*/
@Nullable
public BeanDefinitionHolder getDecoratedDefinition() {
return this.decoratedDefinition;
}
/**
* Specify the {@link AnnotatedElement} defining qualifiers,
* to be used instead of the target class or factory method.
* @since 4.3.3
* @see #setTargetType(ResolvableType)
* @see #getResolvedFactoryMethod()
*/
public void setQualifiedElement(@Nullable AnnotatedElement qualifiedElement) {
this.qualifiedElement = qualifiedElement;
}
/**
* Return the {@link AnnotatedElement} defining qualifiers, if any.
* Otherwise, the factory method and target class will be checked.
* @since 4.3.3
*/
@Nullable
public AnnotatedElement getQualifiedElement() {
return this.qualifiedElement;
}
/**
* Specify a generics-containing target type of this bean definition, if known in advance.
* @since 4.3.3
*/
public void setTargetType(ResolvableType targetType) {
this.targetType = targetType;
}
/**
* Specify the target type of this bean definition, if known in advance.
* @since 3.2.2
*/
public void setTargetType(@Nullable Class<?> targetType) {
this.targetType = (targetType != null ? ResolvableType.forClass(targetType) : null);
}
/**
* Return the target type of this bean definition, if known
* (either specified in advance or resolved on first instantiation).
* @since 3.2.2
*/
@Nullable
public Class<?> getTargetType() {
if (this.resolvedTargetType != null) {
return this.resolvedTargetType;
}
ResolvableType targetType = this.targetType;
return (targetType != null ? targetType.resolve() : null);
}
/**
* Return a {@link ResolvableType} for this bean definition,
* either from runtime-cached type information or from configuration-time
* {@link #setTargetType(ResolvableType)} or {@link #setBeanClass(Class)},
* also considering resolved factory method definitions.
* @since 5.1
* @see #setTargetType(ResolvableType)
* @see #setBeanClass(Class)
* @see #setResolvedFactoryMethod(Method)
*/
@Override
public ResolvableType getResolvableType() {
ResolvableType targetType = this.targetType;
if (targetType != null) {
return targetType;
}
ResolvableType returnType = this.factoryMethodReturnType;
if (returnType != null) {
return returnType;
}
Method factoryMethod = this.factoryMethodToIntrospect;
if (factoryMethod != null) {
return ResolvableType.forMethodReturnType(factoryMethod);
}
return super.getResolvableType();
}
/**
* Determine preferred constructors to use for default construction, if any.
* Constructor arguments will be autowired if necessary.
* @return one or more preferred constructors, or {@code null} if none
* (in which case the regular no-arg default constructor will be called)
* @since 5.1
*/
@Nullable
public Constructor<?>[] getPreferredConstructors() {
return null;
}
/**
* Specify a factory method name that refers to a non-overloaded method.
*/
public void setUniqueFactoryMethodName(String name) {
Assert.hasText(name, "Factory method name must not be empty");
setFactoryMethodName(name);
this.isFactoryMethodUnique = true;
}
/**
* Specify a factory method name that refers to an overloaded method.
* @since 5.2
*/
public void setNonUniqueFactoryMethodName(String name) {
Assert.hasText(name, "Factory method name must not be empty");
setFactoryMethodName(name);
this.isFactoryMethodUnique = false;
}
/**
* Check whether the given candidate qualifies as a factory method.
*/
public boolean isFactoryMethod(Method candidate) {
return candidate.getName().equals(getFactoryMethodName());
}
/**
* Set a resolved Java Method for the factory method on this bean definition.
* @param method the resolved factory method, or {@code null} to reset it
* @since 5.2
*/
public void setResolvedFactoryMethod(@Nullable Method method) {
this.factoryMethodToIntrospect = method;
}
/**
* Return the resolved factory method as a Java Method object, if available.
* @return the factory method, or {@code null} if not found or not resolved yet
*/
@Nullable
public Method getResolvedFactoryMethod() {
return this.factoryMethodToIntrospect;
}
public void registerExternallyManagedConfigMember(Member configMember) {
synchronized (this.postProcessingLock) {
if (this.externallyManagedConfigMembers == null) {
this.externallyManagedConfigMembers = new HashSet<>(1);
}
this.externallyManagedConfigMembers.add(configMember);
}
}
public boolean isExternallyManagedConfigMember(Member configMember) {
synchronized (this.postProcessingLock) {
return (this.externallyManagedConfigMembers != null &&
this.externallyManagedConfigMembers.contains(configMember));
}
}
public void registerExternallyManagedInitMethod(String initMethod) {
synchronized (this.postProcessingLock) {
if (this.externallyManagedInitMethods == null) {
this.externallyManagedInitMethods = new HashSet<>(1);
}
this.externallyManagedInitMethods.add(initMethod);
}
}
public boolean isExternallyManagedInitMethod(String initMethod) {
synchronized (this.postProcessingLock) {
return (this.externallyManagedInitMethods != null &&
this.externallyManagedInitMethods.contains(initMethod));
}
}
public void registerExternallyManagedDestroyMethod(String destroyMethod) {
synchronized (this.postProcessingLock) {
if (this.externallyManagedDestroyMethods == null) {
this.externallyManagedDestroyMethods = new HashSet<>(1);
}
this.externallyManagedDestroyMethods.add(destroyMethod);
}
}
public boolean isExternallyManagedDestroyMethod(String destroyMethod) {
synchronized (this.postProcessingLock) {
return (this.externallyManagedDestroyMethods != null &&
this.externallyManagedDestroyMethods.contains(destroyMethod));
}
}
@Override
public RootBeanDefinition cloneBeanDefinition() {
return new RootBeanDefinition(this);
}
@Override
public boolean equals(@Nullable Object other) {
return (this == other || (other instanceof RootBeanDefinition && super.equals(other)));
}
@Override
public String toString() {
return "Root bean: " + super.toString();
}
}
2 GenericBeanDefinition
普通的 BeanDefinition,任何 Bean 在处理之前都是 GenericBeanDefinition。
/*
* 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
*
* 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 org.springframework.beans.factory.support;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
* GenericBeanDefinition is a one-stop shop for standard bean definition purposes.
* Like any bean definition, it allows for specifying a class plus optionally
* constructor argument values and property values. Additionally, deriving from a
* parent bean definition can be flexibly configured through the "parentName" property.
*
* <p>In general, use this {@code GenericBeanDefinition} class for the purpose of
* registering user-visible bean definitions (which a post-processor might operate on,
* potentially even reconfiguring the parent name). Use {@code RootBeanDefinition} /
* {@code ChildBeanDefinition} where parent/child relationships happen to be pre-determined.
*
* @author Juergen Hoeller
* @since 2.5
* @see #setParentName
* @see RootBeanDefinition
* @see ChildBeanDefinition
*/
@SuppressWarnings("serial")
public class GenericBeanDefinition extends AbstractBeanDefinition {
@Nullable
private String parentName;
/**
* Create a new GenericBeanDefinition, to be configured through its bean
* properties and configuration methods.
* @see #setBeanClass
* @see #setScope
* @see #setConstructorArgumentValues
* @see #setPropertyValues
*/
public GenericBeanDefinition() {
super();
}
/**
* Create a new GenericBeanDefinition as deep copy of the given
* bean definition.
* @param original the original bean definition to copy from
*/
public GenericBeanDefinition(BeanDefinition original) {
super(original);
}
@Override
public void setParentName(@Nullable String parentName) {
this.parentName = parentName;
}
@Override
@Nullable
public String getParentName() {
return this.parentName;
}
@Override
public AbstractBeanDefinition cloneBeanDefinition() {
return new GenericBeanDefinition(this);
}
@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
if (!(other instanceof GenericBeanDefinition)) {
return false;
}
GenericBeanDefinition that = (GenericBeanDefinition) other;
return (ObjectUtils.nullSafeEquals(this.parentName, that.parentName) && super.equals(other));
}
@Override
public String toString() {
if (this.parentName != null) {
return "Generic bean with parent '" + this.parentName + "': " + super.toString();
}
return "Generic bean: " + super.toString();
}
}
3 ChildBeanDefinition
子节点的 BeanDefinition
/*
* Copyright 2002-2017 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
*
* 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 org.springframework.beans.factory.support;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
* Bean definition for beans which inherit settings from their parent.
* Child bean definitions have a fixed dependency on a parent bean definition.
*
* <p>A child bean definition will inherit constructor argument values,
* property values and method overrides from the parent, with the option
* to add new values. If init method, destroy method and/or static factory
* method are specified, they will override the corresponding parent settings.
* The remaining settings will <i>always</i> be taken from the child definition:
* depends on, autowire mode, dependency check, singleton, lazy init.
*
* <p><b>NOTE:</b> Since Spring 2.5, the preferred way to register bean
* definitions programmatically is the {@link GenericBeanDefinition} class,
* which allows to dynamically define parent dependencies through the
* {@link GenericBeanDefinition#setParentName} method. This effectively
* supersedes the ChildBeanDefinition class for most use cases.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see GenericBeanDefinition
* @see RootBeanDefinition
*/
@SuppressWarnings("serial")
public class ChildBeanDefinition extends AbstractBeanDefinition {
@Nullable
private String parentName;
/**
* Create a new ChildBeanDefinition for the given parent, to be
* configured through its bean properties and configuration methods.
* @param parentName the name of the parent bean
* @see #setBeanClass
* @see #setScope
* @see #setConstructorArgumentValues
* @see #setPropertyValues
*/
public ChildBeanDefinition(String parentName) {
super();
this.parentName = parentName;
}
/**
* Create a new ChildBeanDefinition for the given parent.
* @param parentName the name of the parent bean
* @param pvs the additional property values of the child
*/
public ChildBeanDefinition(String parentName, MutablePropertyValues pvs) {
super(null, pvs);
this.parentName = parentName;
}
/**
* Create a new ChildBeanDefinition for the given parent.
* @param parentName the name of the parent bean
* @param cargs the constructor argument values to apply
* @param pvs the additional property values of the child
*/
public ChildBeanDefinition(
String parentName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
super(cargs, pvs);
this.parentName = parentName;
}
/**
* Create a new ChildBeanDefinition for the given parent,
* providing constructor arguments and property values.
* @param parentName the name of the parent bean
* @param beanClass the class of the bean to instantiate
* @param cargs the constructor argument values to apply
* @param pvs the property values to apply
*/
public ChildBeanDefinition(
String parentName, Class<?> beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
super(cargs, pvs);
this.parentName = parentName;
setBeanClass(beanClass);
}
/**
* Create a new ChildBeanDefinition for the given parent,
* providing constructor arguments and property values.
* Takes a bean class name to avoid eager loading of the bean class.
* @param parentName the name of the parent bean
* @param beanClassName the name of the class to instantiate
* @param cargs the constructor argument values to apply
* @param pvs the property values to apply
*/
public ChildBeanDefinition(
String parentName, String beanClassName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
super(cargs, pvs);
this.parentName = parentName;
setBeanClassName(beanClassName);
}
/**
* Create a new ChildBeanDefinition as deep copy of the given
* bean definition.
* @param original the original bean definition to copy from
*/
public ChildBeanDefinition(ChildBeanDefinition original) {
super(original);
}
@Override
public void setParentName(@Nullable String parentName) {
this.parentName = parentName;
}
@Override
@Nullable
public String getParentName() {
return this.parentName;
}
@Override
public void validate() throws BeanDefinitionValidationException {
super.validate();
if (this.parentName == null) {
throw new BeanDefinitionValidationException("'parentName' must be set in ChildBeanDefinition");
}
}
@Override
public AbstractBeanDefinition cloneBeanDefinition() {
return new ChildBeanDefinition(this);
}
@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
if (!(other instanceof ChildBeanDefinition)) {
return false;
}
ChildBeanDefinition that = (ChildBeanDefinition) other;
return (ObjectUtils.nullSafeEquals(this.parentName, that.parentName) && super.equals(other));
}
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(this.parentName) * 29 + super.hashCode();
}
@Override
public String toString() {
return "Child bean with parent '" + this.parentName + "': " + super.toString();
}
}
4 ConfigurableBeanFactory#getMergedBeanDefinition
获取合并后的 Bean 定义,有以下几种情况 没有继承任何类的 Bean, 如 User,返回 RootBeanDefinition
/**
* 返回给定 bean 名称的合并 BeanDefinition,如果需要,将子 bean 定义与其父合并。
* 也合并祖先工厂中的 bean 定义。
* @param beanName the name of the bean to retrieve the merged definition for
* @return a (potentially merged) BeanDefinition for the given bean
* @throws NoSuchBeanDefinitionException if there is no bean definition with the given name
* @since 2.5
*/
BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
5 AbstractBeanFactory#getMergedBeanDefinition
/**
* Return a 'merged' BeanDefinition for the given bean name,
* merging a child bean definition with its parent if necessary.
* <p>This {@code getMergedBeanDefinition} considers bean definition
* in ancestors as well.
* @param name the name of the bean to retrieve the merged definition for
* (may be an alias)
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
@Override
public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
// 返回 bean 名称,必要时去除工厂取消引用前缀,并将别名解析为规范名称。
String beanName = transformedBeanName(name);
// 检查该工厂中是否存在bean定义。
// containsBeanDefinition(beanName) 检查当前 beanName 缓存是否存在
// getParentBeanFactory() instanceof ConfigurableBeanFactory 父类的 getParentBeanFactory 存在且为 ConfigurableBeanFactory 类型
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
}
// 在本地解析合并 bean 定义。
return getMergedLocalBeanDefinition(beanName);
}
6 AbstractBeanFactory#getMergedLocalBeanDefinition
该方法返回一个合并的 RootBeanDefinition,如果指定的 bean 对应一个子 bean 定义,则遍历父 bean 定义
/**
* Return a merged RootBeanDefinition, traversing the parent bean definition
* if the specified bean corresponds to a child bean definition.
* @param beanName the name of the bean to retrieve the merged definition for
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// 进行缓存检查,beanName 对应的 mergedBeanDefinitions 缓存是否存在
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
// 如果存在,并且没有过期
if (mbd != null && !mbd.stale) {
// 直接返回找到的 RootBeanDefinition
return mbd;
}
// 调用重载方法继续获取
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
/**
* Return a RootBeanDefinition for the given top-level bean, by merging with
* the parent if the given bean's definition is a child bean definition.
* @param beanName the name of the bean definition
* @param bd the original bean definition (Root/ChildBeanDefinition)
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
/**
* Return a RootBeanDefinition for the given bean, by merging with the
* parent if the given bean's definition is a child bean definition.
* @param beanName the name of the bean definition
* @param bd the original bean definition (Root/ChildBeanDefinition)
* @param containingBd 如果是内部 bean(对象里面有另一个对象),则包含 bean 定义,
* or {@code null} in case of a top-level bean
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
// 加锁操作
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
// 旧的 RootBeanDefinition
RootBeanDefinition previous = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
// 再次检测 RootBeanDefinition 有没有值,有可能再调用该方法前被其他线程赋值了
mbd = this.mergedBeanDefinitions.get(beanName);
}
// RootBeanDefinition 为空 或者 RootBeanDefinition 过期了
if (mbd == null || mbd.stale) {
// 赋值给旧值
previous = mbd;
// BeanDefinition 的父类为空
if (bd.getParentName() == null) {
// 如果 BeanDefinition 是 RootBeanDefinition 类型
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
// 将 BeanDefinition 包装为 RootBeanDefinition 赋值给 mbd
mbd = new RootBeanDefinition(bd);
}
}
else {
// 子bean定义:需要与父类合并。
BeanDefinition pbd;
try {
// 格式化名称
String parentBeanName = transformedBeanName(bd.getParentName());
// 如果当前名称和父类名称不一致时
if (!beanName.equals(parentBeanName)) {
// 查询父类的 BeanDefinition, 递归查询,如果父类还是父类,则继续向上查询
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
// 走到这里表示,当前 BeanName == parentBeanName,这只有一种情况
// 当前 Bean 的父类存在于另外一个 BeanFactory 中并且是 HierarchicalBeanFactory 层次性的 BeanFactory
// 所以,如果是这种情况,就去父类的 BeanFactory 中查询 Bean 定义
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// 深度克隆父类值,生成 RootBeanDefinition
mbd = new RootBeanDefinition(pbd);
// Bean 定义合并,将子类的属性拷贝到父类上,形成最后的 Bean 定义
mbd.overrideFrom(bd);
}
// 如果之前未配置,则设置默认单例作用域。
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// 如果类中包含的 Bean 为非单例类型,当前 Bean 定义为单例, 则需要将当前 Bean 定义设置为包含 Bean 的作用域
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
// isCacheBeanMetadata 该方法默认值为true,无论何时都需要缓存
if (containingBd == null && isCacheBeanMetadata()) {
// 将当前 RootBeanDefinition 缓存到 mergedBeanDefinitions 中
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
7 Spring BeanDefinition 合并阶段总结
RootBeanDefinition、GenericBeanDefinition、ChildBeanDefinition 都是继承于 AbstractBeanDefinition 。
- RootBeanDefinition 顶层节点的 Bean 定义
- GenericBeanDefinition 未经处理的 Bean 都是 GenericBeanDefinition
- ChildBeanDefinition 子节点的 Bean 定义
合并阶段提供的接口为:ConfigurableBeanFactory#getMergedBeanDefinition(String beanName),该接口提供了一个功能, 根据 BeanName 去获取合并后的 Bean 定义。
ConfigurableBeanFactory#getMergedBeanDefinition(String beanName) 接口的唯一实现类为:AbstractBeanFactory。
getMergedBeanDefinition 具体的合并步骤如下:
- 查询缓存中是否存在 Bean 定义,存在则直接
- 判断当前 Bean 是否有parent,不存在 parent 的情况下,根据当前 Bean 生成 RootBeanDefinition。
- 如果当前 Bean 存在 parent, 先获取 parent 的 BeanDefinition(此处为递归获取,如果父类还有父类,也会获取)
- 将父类的 BeanDefinition 转化为 RootBeanDefinition
- 将当前类的 BeanDefinition 属性复制到 父类的 RootBeanDefinition 上
- 再将合并后的结果存入的缓存 mergedBeanDefinitions 中,以供下次查询使用
Chapter 4 Spring Bean Class 加载阶段
1 概述
2 AbstractAutowireCapableBeanFactory#createBean
将 className 解析成 Class 的入口在 Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
3 AbstractBeanFactory#resolveBeanClass
@Nullable
protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
throws CannotLoadBeanClassException {
try {
// 执行到这里的时候,虽然 beanClass 有值,但是 hasBeanClass 的标识却为 false
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
// 判断系统的安全管理器是否激活
if (System.getSecurityManager() != null) {
// 如果系统的安全管理器激活,设置权限并执行
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
return doResolveBeanClass(mbd, typesToMatch);
}
}
catch (PrivilegedActionException pae) {
ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
}
catch (ClassNotFoundException ex) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
}
catch (LinkageError err) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
}
}
4 AbstractBeanFactory#doResolveBeanClass
@Nullable
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
throws ClassNotFoundException {
// 获取当前系统的 classLoader
ClassLoader beanClassLoader = getBeanClassLoader();
ClassLoader dynamicLoader = beanClassLoader;
boolean freshResolve = false;
// 这里没有设置类型的时候不会走入
if (!ObjectUtils.isEmpty(typesToMatch)) {
// When just doing type checks (i.e. not creating an actual instance yet),
// use the specified temporary class loader (e.g. in a weaving scenario).
ClassLoader tempClassLoader = getTempClassLoader();
if (tempClassLoader != null) {
dynamicLoader = tempClassLoader;
freshResolve = true;
if (tempClassLoader instanceof DecoratingClassLoader) {
DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
for (Class<?> typeToMatch : typesToMatch) {
dcl.excludeClass(typeToMatch.getName());
}
}
}
}
// 获取 class 的全路径名称
String className = mbd.getBeanClassName();
if (className != null) {
// 格式化解析全路径名称
Object evaluated = evaluateBeanDefinitionString(className, mbd);
// 获取的 className 和解析后的名称不相同时执行
if (!className.equals(evaluated)) {
// A dynamically resolved expression, supported as of 4.2...
if (evaluated instanceof Class) {
return (Class<?>) evaluated;
}
else if (evaluated instanceof String) {
className = (String) evaluated;
freshResolve = true;
}
else {
throw new IllegalStateException("Invalid class name expression result: " + evaluated);
}
}
if (freshResolve) {
// When resolving against a temporary class loader, exit early in order
// to avoid storing the resolved Class in the bean definition.
if (dynamicLoader != null) {
try {
// 使用类加载器加载 class
return dynamicLoader.loadClass(className);
}
catch (ClassNotFoundException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
}
}
}
// 使用类加载器加载
return ClassUtils.forName(className, dynamicLoader);
}
}
// Resolve regularly, caching the result in the BeanDefinition...
return mbd.resolveBeanClass(beanClassLoader);
}
5 AbstractBeanDefinition#resolveBeanClass
@Nullable
public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
// 获取 BeanClassName
String className = getBeanClassName();
if (className == null) {
return null;
}
// 根据 BeanClassName 使用反射创建 beanDefinition 对应的类
Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
this.beanClass = resolvedClass;
return resolvedClass;
}
Chapter 5 Spring Bean 实例化前阶段
1 InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor Bean 实例化回调的API,提供了如下三个生命周期接口:
- postProcessBeforeInstantiation 实例化前的回调接口
- postProcessAfterInstantiation 实例化后的回调接口
- postProcessProperties 赋值回调
- postProcessPropertyValues 旧接口,5.1以后被 postProcessProperties 替代了
/*
* 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
*
* 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 org.springframework.beans.factory.config;
import java.beans.PropertyDescriptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.lang.Nullable;
/**
* Subinterface of {@link BeanPostProcessor} that adds a before-instantiation callback,
* and a callback after instantiation but before explicit properties are set or
* autowiring occurs.
*
* <p>Typically used to suppress default instantiation for specific target beans,
* for example to create proxies with special TargetSources (pooling targets,
* lazily initializing targets, etc), or to implement additional injection strategies
* such as field injection.
*
* <p><b>NOTE:</b> This interface is a special purpose interface, mainly for
* internal use within the framework. It is recommended to implement the plain
* {@link BeanPostProcessor} interface as far as possible, or to derive from
* {@link InstantiationAwareBeanPostProcessorAdapter} in order to be shielded
* from extensions to this interface.
*
* @author Juergen Hoeller
* @author Rod Johnson
* @since 1.2
* @see org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#setCustomTargetSourceCreators
* @see org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator
*/
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
* Apply this BeanPostProcessor <i>before the target bean gets instantiated</i>.
* The returned bean object may be a proxy to use instead of the target bean,
* effectively suppressing default instantiation of the target bean.
* <p>If a non-null object is returned by this method, the bean creation process
* will be short-circuited. The only further processing applied is the
* {@link #postProcessAfterInitialization} callback from the configured
* {@link BeanPostProcessor BeanPostProcessors}.
* <p>This callback will be applied to bean definitions with their bean class,
* as well as to factory-method definitions in which case the returned bean type
* will be passed in here.
* <p>Post-processors may implement the extended
* {@link SmartInstantiationAwareBeanPostProcessor} interface in order
* to predict the type of the bean object that they are going to return here.
* <p>The default implementation returns {@code null}.
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return the bean object to expose instead of a default instance of the target bean,
* or {@code null} to proceed with default instantiation
* @throws org.springframework.beans.BeansException in case of errors
* @see #postProcessAfterInstantiation
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getBeanClass()
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getFactoryMethodName()
*/
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
/**
* Perform operations after the bean has been instantiated, via a constructor or factory method,
* but before Spring property population (from explicit properties or autowiring) occurs.
* <p>This is the ideal callback for performing custom field injection on the given bean
* instance, right before Spring's autowiring kicks in.
* <p>The default implementation returns {@code true}.
* @param bean the bean instance created, with properties not having been set yet
* @param beanName the name of the bean
* @return {@code true} if properties should be set on the bean; {@code false}
* if property population should be skipped. Normal implementations should return {@code true}.
* Returning {@code false} will also prevent any subsequent InstantiationAwareBeanPostProcessor
* instances being invoked on this bean instance.
* @throws org.springframework.beans.BeansException in case of errors
* @see #postProcessBeforeInstantiation
*/
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
/**
* Post-process the given property values before the factory applies them
* to the given bean, without any need for property descriptors.
* <p>Implementations should return {@code null} (the default) if they provide a custom
* {@link #postProcessPropertyValues} implementation, and {@code pvs} otherwise.
* In a future version of this interface (with {@link #postProcessPropertyValues} removed),
* the default implementation will return the given {@code pvs} as-is directly.
* @param pvs the property values that the factory is about to apply (never {@code null})
* @param bean the bean instance created, but whose properties have not yet been set
* @param beanName the name of the bean
* @return the actual property values to apply to the given bean (can be the passed-in
* PropertyValues instance), or {@code null} which proceeds with the existing properties
* but specifically continues with a call to {@link #postProcessPropertyValues}
* (requiring initialized {@code PropertyDescriptor}s for the current bean class)
* @throws org.springframework.beans.BeansException in case of errors
* @since 5.1
* @see #postProcessPropertyValues
*/
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
/**
* Post-process the given property values before the factory applies them
* to the given bean. Allows for checking whether all dependencies have been
* satisfied, for example based on a "Required" annotation on bean property setters.
* <p>Also allows for replacing the property values to apply, typically through
* creating a new MutablePropertyValues instance based on the original PropertyValues,
* adding or removing specific values.
* <p>The default implementation returns the given {@code pvs} as-is.
* @param pvs the property values that the factory is about to apply (never {@code null})
* @param pds the relevant property descriptors for the target bean (with ignored
* dependency types - which the factory handles specifically - already filtered out)
* @param bean the bean instance created, but whose properties have not yet been set
* @param beanName the name of the bean
* @return the actual property values to apply to the given bean (can be the passed-in
* PropertyValues instance), or {@code null} to skip property population
* @throws org.springframework.beans.BeansException in case of errors
* @see #postProcessProperties
* @see org.springframework.beans.MutablePropertyValues
* @deprecated as of 5.1, in favor of {@link #postProcessProperties(PropertyValues, Object, String)}
*/
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
2 BeforeInstantiationBeanLifeCycleDemo
{@link InstantiationAwareBeanPostProcessor}实例化前阶段使用案例展示。 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 该方法的主要作用为:如果该方法返回了对象,在依赖查找过程中,将直接返回该对象(代理对象)。如果返回的null,则继续执行依赖查找,创建原有对象。
package com.geekbang.thinking.in.spring.bean.lifecycle;
import com.geekbang.spring.ioc.container.overview.annotation.Super;
import com.geekbang.spring.ioc.container.overview.domain.ChildUser;
import com.geekbang.spring.ioc.container.overview.domain.SuperUser;
import com.geekbang.spring.ioc.container.overview.domain.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.util.ObjectUtils;
/**
* @ClassName BeforeInstantiationBeanLifeCycleDemo
* @Description {@link InstantiationAwareBeanPostProcessor}实例化前阶段使用案例展示
* @Author WQ
* @Date 2022/8/11 18:05
* @Version 1.0
*/
public class BeforeInstantiationBeanLifeCycleDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.addBeanPostProcessor(new ChildUserInstantiationAwareBeanPostProcessor());
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
String location = "META-INF/dependency-lookup-context.xml";
reader.loadBeanDefinitions(location);
User user = beanFactory.getBean("user", User.class);
System.out.println(user);
SuperUser superUser = beanFactory.getBean("superUser", SuperUser.class);
System.out.println(superUser);
}
static class ChildUserInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals("superUser", beanName) && beanClass.equals(SuperUser.class)) {
ChildUser childUser = new ChildUser();
childUser.setAge(22);
return childUser;
}
return null;
}
}
}
3 AbstractAutowireCapableBeanFactory#createBean
createBean 是创建 Bean 的过程,在进行实例化之前,会调用 resolveBeforeInstantiation 接口,进行实例化前的扩展执行。
resolveBeforeInstantiation 在解析创建实例之前有一次机会返回一个代理对象,而不是原有的 Bean。 使用场景在 RPC 或者 AOP 中可以进行对象拦截并返回。
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 让 BeanPostProcessors 有机会返回一个代理而不是目标 bean 实例。
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
// 如果代理对象不为空,则返回代理对象,完成 creatBean 操作
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
4 AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
/**
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the shortcut-determined bean instance, or {@code null} if none
*/
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 执行实例化前的扩展的回调接口
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
// 将实例化前的解析标识该为 true
mbd.beforeInstantiationResolved = (bean != null);
}
// 返回代理对象或者 null
return bean;
}
5 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
// 遍历所有的扩展,所有的 BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 如果是实例化扩展回调
if (bp instanceof InstantiationAwareBeanPostProcessor) {
// 类型转换
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 执行相应的扩展回调,也就是我们 Demo 中添加的扩展类
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
// result != null 表示返回的是代理对象,直接将代理对象返回
return result;
}
}
}
return null;
}