乐趣区

Spring源码之BeanDefinition类分析

Spring 版本为 5.1.5
用过 spring 的人都知道,我们将对象注入到 spring 容器中,交给 spring 来帮我们管理。这种对象我们称之为 bean 对象。但是这些 bean 对象在 spring 容器中,到底是以什么形式存在,具有哪些属性、行为呢?今天我们进入到 spring 源码来一探究竟。
bean 的创建工厂 BeanFactory 有个默认实现类 DefaultListableBeanFactory,内部有个存放所有注入 bean 对象信息的 Map
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
Map 的 value 对象 BeanDefinition 就是 spring 中对 bean 的定义和描述,具体概述如下:

属性
行为
解释

parentName
String getParentName();void setParentName(@Nullable String parentName);
bean 定义对象的父类定义对象名称

beanClassName
String getBeanClassName();void setBeanClassName(@Nullable String beanClassName);
bean 对象的实际 class 类

scope
String getScope();void setScope(@Nullable String scope);
bean 对象是否为单例 <singleton 或者 prototype>

lazyInit
boolean isLazyInit();void setLazyInit(boolean lazyInit);
是否懒加载

dependsOn
String[] getDependsOn();void setDependsOn(@Nullable String… dependsOn);
设置依赖的 bean 对象,被依赖的 bean 对象总是会比当前 bean 对象先创建

autowireCandidate
boolean isAutowireCandidate();void setAutowireCandidate(boolean autowireCandidate);
设置是否可以自动注入。只对 @Autowired 注解有效,配置文件中可以通过 property 显示注入

primary
boolean isPrimary();void setPrimary(boolean primary);
配置 bean 为主要候选 bean。当同一个接口的多个实现类或者一个类多次注入到 spring 容器时,通过该属性来配置某个 bean 为主候选 bean,通过类型来注入时,默认为使用主候选 bean 注入

factoryBeanName
String getFactoryBeanName();void setFactoryBeanName(@Nullable String factoryBeanName);
设置创建 bean 的工厂名称

factoryMethodName
String getFactoryMethodName();void setFactoryMethodName(@Nullable String factoryMethodName);
设置创建 bean 的工厂中,创建 bean 的具体方法

initMethodName
String getInitMethodName();void setInitMethodName(@Nullable String initMethodName);
设置创建 bean 时,默认初始化的方法

destroyMethodName
String getDestroyMethodName();void setDestroyMethodName(@Nullable String destroyMethodName);
设置销毁 bean 时调用的方法名称。注意需要调用 context 的 close() 方法才会调用

role
int getRole();void setRole(int role);
设置 bean 的分类

description
String getDescription();void setDescription(@Nullable String description);
对 bean 对象的描述

注意:BeanDefinition 是一个接口,内部只定义了 bean 对象的一些基本行为。上表中的属性在 BeanDefinition 中并不是真实存在的,只是通过 set、get 方法来设置和获取。以下抽取出部分 BeanDefinition 源代码供大家感知下
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
/**
* Override the target scope of this bean, specifying a new scope name.
* @see #SCOPE_SINGLETON
* @see #SCOPE_PROTOTYPE
*/
void setScope(@Nullable String scope);

/**
* Return the name of the current target scope for this bean,
* or {@code null} if not known yet.
*/
@Nullable
String getScope();
}
实际使用
假设有以下两个 bean,Java 代码如下
MyTestBean
package com.yuanweiquan.learn.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Description;

public class MyTestBean {
@Autowired
private AutowireCandidateBean autowireCandidateBean;

public void init() {
System.out.println(“inti MyTestBean”);
}

public AutowireCandidateBean getAutowireCandidateBean() {
return autowireCandidateBean;
}
public void setAutowireCandidateBean(AutowireCandidateBean bean) {
this.autowireCandidateBean = bean;
}
}

AutowireCandidateBean
package com.yuanweiquan.learn.bean;

public class AutowireCandidateBean {
public void initBean() {
System.out.println(“init AutowireCandidateBean”);
}

public void destroyBean() {
System.out.println(“destroy AutowireCandidateBean”);
}
}
下面看如何在配置文件 applicationContext.xml 来进行配置
<bean id=”myTestBean” class=”com.yuanweiquan.learn.bean.MyTestBean”
depends-on=”autowireCandidateBean”
init-method=”init”/>

<bean id=”autowireCandidateBean”
class=”com.yuanweiquan.learn.bean.AutowireCandidateBean”
init-method=”initBean”
autowire-candidate=”true”
destroy-method=”destroyBean”
scope=”singleton”
parent=”myTestBean”
lazy-init=”default”
primary=”true”>
<description>autowireCandidateBean description</description>
</bean>
接下来就是测试代码
public class FirstContainer {
public static void main(String[] args) {
FileSystemXmlApplicationContext factory =
new FileSystemXmlApplicationContext(“classpath:applicationContext.xml”);
BeanDefinition myTestBeanDefinition =
factory.getBeanFactory().getBeanDefinition(“autowireCandidateBean”);
// 输出
System.out.println(“bean description:” + myTestBeanDefinition.getDescription());
System.out.println(“bean class name:” + myTestBeanDefinition.getBeanClassName());
System.out.println(“parent name:” + myTestBeanDefinition.getParentName());
System.out.println(“scope:” + myTestBeanDefinition.getScope());
System.out.println(“is lazyinit:” + myTestBeanDefinition.isLazyInit());
System.out.println(“depends On:” + myTestBeanDefinition.getDependsOn());
System.out.println(“is autowireCandidate:” + myTestBeanDefinition.isAutowireCandidate());
System.out.println(“is primary:” + myTestBeanDefinition.isPrimary());
System.out.println(“factory bean name:”+myTestBeanDefinition.getFactoryBeanName());
System.out.println(“factory bean method name:” + myTestBeanDefinition.getFactoryMethodName());
System.out.println(“init method name:” + myTestBeanDefinition.getInitMethodName());
System.out.println(“destory method name:” + myTestBeanDefinition.getDestroyMethodName());
System.out.println(“role:” + myTestBeanDefinition.getRole());

// 关闭 context,否则不会调用 bean 的销毁方法
factory.close();
}
}
控制台输出如下
init AutowireCandidateBean
inti MyTestBean
bean description:autowireCandidateBean description
bean class name:com.yuanweiquan.learn.bean.AutowireCandidateBean
parent name:myTestBean
scope:singleton
is lazyinit:false
depends On:null
is autowireCandidate:true
is primary:true
factory bean name:null
factory bean method name:null
init method name:initBean
destory method name:destroyBean
role:0
destroy AutowireCandidateBean
到此为止,通过上面的信息,我们能清晰的看到各属性对应的值。上述测试代码的目的是让我们大家能看到 bean 在 spring 容器中,以什么样子的形式存在,具体有哪些属性,属性的值以及默认值是多少。也算初步的揭开了 spring 容器中 bean 的面纱,其实并没有我们想象中的那么神秘。至于各属性的详细使用和注意事项,后续会有单独的文章来解析,尽情期待!

退出移动版