Spring源码分析系列
Spring源码分析-启动流程浅析
Spring源码分析-Spring源码分析-BeanDefinition
Spring源码分析-Bean生命周期概述
Spring源码分析-Bean生命周期查找与注册
Spring源码分析-Bean生命周期查找与注册(2)
文章目录
前言
BeanDefinition相当于Bean meta信息,后续创建Bean对象都需要依据BeanDefinition,因此这里需要介绍一下
一、BeanDefinition
BeanDefinition是一个接口,接口定义如下:
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
/**
* 单例bean
*/
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
/**
* 原型bean
*/
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
/**
* bean的Role属性 现在基本废弃
*/
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
// Modifiable attributes
// 设置父BeanDefinition名称
void setParentName(@Nullable String parentName);
@Nullable String getParentName();
/**
* bean全类名称
*/
void setBeanClassName(@Nullable String beanClassName);
@Nullable String getBeanClassName();
/**
* 设置bean的作用域 单例 或者 原型
*/
void setScope(@Nullable String scope);
@Nullable String getScope();
/**
* 懒加载模式
*/
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
/**
* Set the names of the beans that this bean depends on being initialized.
* The bean factory will guarantee that these beans get initialized first.
*/
void setDependsOn(@Nullable String... dependsOn);
@Nullable String[] getDependsOn();
/**
* Set whether this bean is a candidate for getting autowired into some other bean.
* <p>Note that this flag is designed to only affect type-based autowiring.
* It does not affect explicit references by name, which will get resolved even
* if the specified bean is not marked as an autowire candidate. As a consequence,
* autowiring by name will nevertheless inject a bean if the name matches.
*/
void setAutowireCandidate(boolean autowireCandidate);
/**
* Return whether this bean is a candidate for getting autowired into some other bean.
*/
boolean isAutowireCandidate();
/**
* 设置当前bean为主要的, @Primary
*/
void setPrimary(boolean primary);
boolean isPrimary();
/**
* Specify the factory bean to use, if any.
* This the name of the bean to call the specified factory method on.
* @see #setFactoryMethodName
*/
void setFactoryBeanName(@Nullable String factoryBeanName);
@Nullable String getFactoryBeanName();
/**
* Specify a factory method, if any. This method will be invoked with
* constructor arguments, or with no arguments if none are specified.
* The method will be invoked on the specified factory bean, if any,
* or otherwise as a static method on the local bean class.
* @see #setFactoryBeanName
* @see #setBeanClassName
*/
void setFactoryMethodName(@Nullable String factoryMethodName);
/**
* Return a factory method, if any.
*/
@Nullable
String getFactoryMethodName();
/**
* Return the constructor argument values for this bean.
* <p>The returned instance can be modified during bean factory post-processing.
* @return the ConstructorArgumentValues object (never {@code null})
*/
ConstructorArgumentValues getConstructorArgumentValues();
/**
* Return if there are constructor argument values defined for this bean.
* @since 5.0.2
*/
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
/**
* Return the property values to be applied to a new instance of the bean.
* <p>The returned instance can be modified during bean factory post-processing.
* @return the MutablePropertyValues object (never {@code null})
*/
MutablePropertyValues getPropertyValues();
/**
* Return if there are property values defined for this bean.
* @since 5.0.2
*/
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
/**
* Set the name of the initializer method.
* @since 5.1
*/
void setInitMethodName(@Nullable String initMethodName);
/**
* Return the name of the initializer method.
* @since 5.1
*/
@Nullable String getInitMethodName();
/**
* Set the name of the destroy method.
* @since 5.1
*/
void setDestroyMethodName(@Nullable String destroyMethodName);
/**
* Return the name of the destroy method.
* @since 5.1
*/
@Nullable String getDestroyMethodName();
void setRole(int role);
int getRole();
/**
* Set a human-readable description of this bean definition.
* @since 5.1
*/
void setDescription(@Nullable String description);
/**
* Return a human-readable description of this bean definition.
*/
@Nullable String getDescription();
// Read-only attributes
/**
* Return a resolvable type for this bean definition,
* based on the bean class or other specific metadata.
* <p>This is typically fully resolved on a runtime-merged bean definition
* but not necessarily on a configuration-time definition instance.
* @return the resolvable type (potentially {@link ResolvableType#NONE})
* @since 5.2
* @see ConfigurableBeanFactory#getMergedBeanDefinition
*/
ResolvableType getResolvableType();
/**
* 是否为单例
*/
boolean isSingleton();
/**
* 是否为原型
*/
boolean isPrototype();
/**
* Return whether this bean is "abstract", that is, not meant to be instantiated.
*/
boolean isAbstract();
/**
* Return a description of the resource that this bean definition
* came from (for the purpose of showing context in case of errors).
*/
@Nullable String getResourceDescription();
/**
* Return the originating BeanDefinition, or {@code null} if none.
* <p>Allows for retrieving the decorated bean definition, if any.
* <p>Note that this method returns the immediate originator. Iterate through the
* originator chain to find the original BeanDefinition as defined by the user.
*/
@Nullable BeanDefinition getOriginatingBeanDefinition();
}
BeanDefinition接口中注入比较详细,大家可以参考源码。主要包括如下属性:bean的作用域,bean是否为Primary,bean是否需要FactoryBean,Init/Destroy方法等。
二、AbstractBeanDefinition
spring代码优秀之处,基本上所有的接口,它都会提供一个实现类,而这个实现类往往都是抽象的(Abstract)。我们接下来看一下AbstractBeanDefinition做了哪些工作
2.1、核心字段
@Nullable
private volatile Object beanClass; //bean name
@Nullable
private String scope = SCOPE_DEFAULT; //作用域 SCOPE_SINGLETON
private boolean abstractFlag = false; //是否为抽象
@Nullable
private Boolean lazyInit;
private int autowireMode = AUTOWIRE_NO; //自动注入
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
@Nullable
private String[] dependsOn;
private boolean autowireCandidate = true;
//是否为主要的, 在按照类型给属性注入时,若出现冲突则查看是否存在@Primary注解 当存在这个注解则字段为true
private boolean primary = false;
@Nullable
private String factoryBeanName; //工厂bean名字
@Nullable
private String factoryMethodName; //工厂方法名字
@Nullable
private ConstructorArgumentValues constructorArgumentValues;
@Nullable
private MutablePropertyValues propertyValues;
private MethodOverrides methodOverrides = new MethodOverrides();
@Nullable
private String initMethodName;
@Nullable
private String destroyMethodName;
看到这里不知道大家是否感觉到,这个数据结构很像spring.xml中配置项,不错,这个类(接口)就是spring.xml文件抽像模型。
2.2、核心方法
/**
* Specify the class for this bean.
* @see #setBeanClassName(String)
*/
public void setBeanClass(@Nullable Class<?> beanClass) {
this.beanClass = beanClass;
}
/**
* Specify the bean class name of this bean definition.
*/
@Override
public void setBeanClassName(@Nullable String beanClassName) {
this.beanClass = beanClassName;
}
public String getBeanClassName() {
Object beanClassObject = this.beanClass;
if (beanClassObject instanceof Class) {
return ((Class<?>) beanClassObject).getName();
}
else {
return (String) beanClassObject;
}
}
public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
String className = getBeanClassName();
if (className == null) {
return null;
}
Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
this.beanClass = resolvedClass;
return resolvedClass;
}
2.2、BeanDefinition扫描
AbstractBeanDefinition并没有提供注册的功能,所以注册是在外部实现的,这也体现了一种设计模式:单一职责模式。
在上一篇介绍Spring源码分析-启动流程浅析中有提到会进行包扫描,这个扫描过程其实就是注册BeanDefinition。
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
//扫描组件 返回的类型是BeanDefinition,实际是ScannedGenericBeanDefinition
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {//判断registry中是否存在BeanDefinition 如果没有则创建
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);//注册BeanDefinition
}
}
}
return beanDefinitions;
}
2.3、BeanDefinition注册
在注解场景下,入口类AnnotationConfigApplicationContext继承GenericApplicationContext,在GenericApplicationContext中有一个属性用于保存BeanDefinition
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
//DefaultListableBeanFactory, 默认Bean工厂,用于产生bean对象
private final DefaultListableBeanFactory beanFactory;
...
}
DefaultListableBeanFactory核心字段
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** 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. key=bean名字 value=BeanDefinition */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** Map from bean name to merged BeanDefinitionHolder. */
private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = 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. 保存bean definition name */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
/** List of names of manually registered singletons, in registration order. */
private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);
...
}
通过上面的源码可知,这些map,list就是用于存与BeanDefinition相关的内容,下面是注册BeanDefinition核心方法
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) {//表示已经存在BeanDefinition
if (!isAllowBeanDefinitionOverriding()) {//是否允许覆盖已经存在BeanDefinition
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 {//BeanDefinition不存在
if (hasBeanCreationStarted()) {// 非启动流程注册beanDefinition, 例如动态注册
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);//放到map中
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {//启动注册阶段
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);//放到map中
this.beanDefinitionNames.add(beanName); //保存注册的beanName
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
2.4、动态注册Bean
public class UserService {
private Map<String, User> map = new ConcurrentHashMap<>();
public UserService() {
System.out.println("UserService init....");
}
public User getUser(String name) {
return map.get(name);
}
public void addUser(User user) {
map.put(user.getUsername(), user);
}
}
public class WApp {
public static void main(String[] args) {
GenericApplicationContext context = new AnnotationConfigApplicationContext("com.worker");
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(UserService.class);
context.registerBeanDefinition("userService", beanDefinition); //动态注册BeanDefinition
//获取bean时,如果bean不存在则去查找是否存在BeanDefinition,如果存在则根据BeanDefinition实例化Bean
System.out.println(context.getBean("userService"));
}
}
总结
总体来说,BeanDefinition相关的内容不是很复杂,只要知道BeanDefinition的作用以及包扫描的作用即可。