什么是 BeanDefinition? 以及 Spring 怎么创建一个 bean
目录概念代码举例源码剖析模拟构造器反射生成对象实例概念它是用来描述 Bean 的,里面存放着关于 Bean 的一系列信息,比如 Bean 的作用域,Bean 所对应的 class, 是否懒加载,是否 Primary 等等。有了它 Spring 容器就掌握了实例化 bean 所需要的一些重要信息,才可以对其进行实例化。代码举例实体类代码public class User {private Strin
目录
概述
BeanDefinition 是用来描述 Bean 的,里面存放着关于 Bean 的一系列信息,比如 Bean 的作用域,Bean 所对应的 class, 是否懒加载,是否 Primary 等等。有了它 Spring 容器就掌握了实例化 bean 所需要的一些重要信息,Spring 才可以对其进行实例化。
这里你可能会想,Spring 实例化一个对象怎么这么复杂,我们自己实例化的时候,不就拿到对应的类,new 一下不就完事了么,哪里需要什么 beanDefinition, 而 Spring 容器的作用不就是替我们保存一些实例,我们需要的时候向他索取,那么它也 new 一堆对象保存着不就行了么。
其实问题也就出在 new 一堆对象这件事上,Spring容器管理着很多很多对象,比如你写一个@Component 注解,它就要实例化一个对象保存着,那么当你启动 Spring 容器的时候面对那么多要实例化的对象,它要先去实例化谁呢?比如说,你可能用了 @DepentOn 注解,就意味着一个 bean 是要优先于另外一个 bean 被实例化出来的。如果你用了@Lazy 注解,那么 Spring 容器启动的时候并不会实例化这个bean,而是等你真正问 Spring 容器要这个实例的时候,它才会给你创建一个 bean 出来。此外有的 bean是多例,而有的是单例,这样的话是不是发现只用一个类来 new 一个对象是不是根本满足不了上面的需求了。所以就有了 beanDefinition 的概念。它描述了 bean 的各种信息。使得 spring 容器能够很好的实例化管理 bean。
代码举例
实体类代码
public class User {
private String name;
private String sex;
public User() {
}
public User(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
测试代码:
public class TestDefinitionMain {
public static void main(String[] args) {
//实例化一个容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//实例化一个 beanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition(User.class);
//注册 beanDefinition
beanFactory.registerBeanDefinition("user1", beanDefinition);
//从容器里获取 bean 实例,如果没有的话,会去创建一个 bean 并返回
User user1 = beanFactory.getBean("user1", User.class);
System.out.println(user1);
//也可以通过操作 beanDefinition, 传入构造方法的参数,进而影响实例化 bean
//实例化一个 beanDefinition
RootBeanDefinition beanDefinition2 = new RootBeanDefinition(User.class);
//添加构造方法的参数
ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
constructorArgumentValues.addIndexedArgumentValue(0, "cison");
constructorArgumentValues.addIndexedArgumentValue(1, "男");
beanDefinition2.setConstructorArgumentValues(constructorArgumentValues);
//注册bean定义
beanFactory.registerBeanDefinition("user2", beanDefinition2);
User user2 = beanFactory.getBean("user2", User.class);
System.out.println(user2);
}
}
运行结果如下,至此我们已经通过注册 bean 定义,进而在容器中实例化一个 bean:
User{name='null', sex='null'}
User{name='cison', sex='男'}
源码剖析
从上面实例代码可以看到,主要的两个方法为 beanFactory.registerBeanDefinition() 和beanFactory.getBean(),分别剖析一下这两个方法到底做了什么。
- 点进去 beanFactory.registerBeanDefinition() ,源码如下:
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");
//我们所用的是 RootBeanDefinition, 所以 if 条件这里不用考虑
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//判断是否已经注册了该 bean 的 bean定义,很明显我们第一次注册,这里获取为空,故这个 if 条件也跳过
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 {
//这里判断bean是否已经开始创建,很明显这里第一次注册bean定义,是没有的进行创建的
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;
removeManualSingletonName(beanName);
}
}
else {
//最终逻辑会走到这里
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
从上面可以看到,代码最终会走到如下代码段,由此可知,注册bean定义,其实就是在将bean定义的信息,保存到 bean 容器的两个局部变量里,其中 beanDefinitionMap 保存bean名称和bean定义的映射关系,beanDefinitionNames 保存所有bean的名称。
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
- beanFactory.getBean()
这是创建 bean 的方法,点进去可以看到如下代码
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
可以看到真正创建 bean 的方法为 doGetBean(),继续往下走
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//该方法判断该 bean 是否有别名,如果有的话就转换一下名称
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//该方法从三级缓存里尝试获取 bean,因为当前是第一次创建,故返回值为 null, 故下面 if 逻辑不会进去
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
// 与下面的 prototype 的 bean 不同,如果创建单例 bean 的时候发现该 bean 正在被创建,这说明出现了循环依赖,但是并没有立刻抛出异常,而是会将当前还没有完全创建好的 bean 返回(当然这也可能会出现问题,后面文章再分析)
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// Spring 只解决了单例 bean 的循环依赖问题,如果是 prototype 类型的 bean 出现了循环依赖则会跑出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 如果当前容器没有获取到bean定义,则会尝试从父容器中获取
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 如果当前容器和父容器中都有改bean定义,就会将二者合并一下
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 如果配置了 @Dependon, 那么就会创建它所依赖的 bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 如果互相dependson, 就会抛出异常,注意这里不是循环依赖,而是二者都标注了 @DependOn 对方的注解,都想让对方先创建出来
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
// 创建当前 bean 依赖的 bean, 也是调用 getBean 方法
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
// 创建单例 bean, 其中 getSingleton 方法是创建 bean 之前进行一写预备工作,createBean 是一个回调方法,该方法是真正实例化 bean 的地方
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//.. 省略部分处理异常代码
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// ....省略部分代码
return (T) bean;
}
通过以上代码及注释,我们会走到如下代码这一行,这里是获取 bean 定义的,那么怎么获取呢,由上面注册bean定义的流程可以猜测,因为注册bean定义的时候,其实是把 bean 定义放入到了容器的一个局部变量 beanDefinitionMap 里,那么当要获取 bean 定义的时候,最终应该也是是从beanDefinitionMap 中来根据名称获取bean定义的。下面我们就继续跟进下面这行代码,来验证我们的猜想。
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
点进去 getMergedLocalBeanDefinition 可以看到
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
//这一行是获取合并之后的 bean 定义的,因为我们目前没有涉及与父 bean 的合并,故获取到 null
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
//最终会走到这一行
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
我们留意到最后一行调用方法的第二个参数,是调用另外一个方法的返回值,我们跟进getBeanDefinition(beanName)
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;
}
我们可以看到,最终果然是从 beanDefinitionMap 中获取到的 bean 定义。至于getMergedBeanDefinition 方法,它是用来合并父亲和孩子之间的bean定义的,目前我们不需要,故暂不讨论。接着我们返回创建 bean 的主流程中去。
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
这里就得到了 bean 定义,然后接下来的核心代码如下
//首先从bean定义中获取 dependOn 信息, 在声明bean的时候可以使用 @Dependon 注解指定在哪些bean创建之后再创建当前bean,我们样例中没有配置,故这里获取到 null,
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
//单例bean的创建流程
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
由上也可以看到 beanDefinition 的作用,可以看到它存储了 bean 的 dependOn 信息和作用域信息,用于控制创建 bean 的流程, 接下来就是真正创建 bean 的流程了,getSingleton 传入bean名称和一个钩子函数,在 getSingleton 方法里有这个一行代码 singletonObject = singletonFactory.getObject(); 这就是调用钩子函数来创建bean实例,所以我们这里直接跟进钩子函数的 createBean(beanName, mbd, args) 方法
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.
//这里是常识创建代理对象,因为我们样例没有配置代理,故这里获取到 null
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 {
//创建普通 bean 的方法
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);
}
}
上面这段代码有两段逻辑,先尝试创建代理对象,如果该 bean 需要被代理,那么就会创建代理对象成功并返回,否则就会进入下面创建普通 bean 的流程 doCreateBean(beanName, mbdToUse, args)
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//在这里通过构造器反射获取到对象实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
该方法里获得实例对象是这一行代码,它底层比较复杂,但是原理就是获取实例类的构造器,通过反射生成一个对象。至此,我们通过getBean()方法就得到了一个实例 bean,后续会有一些初始化,实例化,增强的逻辑,这里暂时就不展开了。
instanceWrapper = createBeanInstance(beanName, mbd, args);
模拟构造器反射生成对象实例
public class TestDefinitionMain {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//实例化一个容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//实例化一个 beanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition(User.class);
//注册 beanDefinition
beanFactory.registerBeanDefinition("user1", beanDefinition);
//从容器里获取 bean 实例,如果没有的话,会去创建一个 bean 并返回
User user1 = beanFactory.getBean("user1", User.class);
System.out.println(user1);
//也可以通过操作 beanDefinition, 传入构造方法的参数,进而影响实例化 bean
//实例化一个 beanDefinition
RootBeanDefinition beanDefinition2 = new RootBeanDefinition(User.class);
//添加构造方法的参数
ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
constructorArgumentValues.addIndexedArgumentValue(0, "cison");
constructorArgumentValues.addIndexedArgumentValue(1, "男");
beanDefinition2.setConstructorArgumentValues(constructorArgumentValues);
//注册bean定义
beanFactory.registerBeanDefinition("user2", beanDefinition2);
User user2 = beanFactory.getBean("user2", User.class);
System.out.println(user2);
//构造器反射获取实例 candidate.newInstance();
Constructor<?>[] candidates = User.class.getDeclaredConstructors();
for (Constructor candidate : candidates) {
int parameterCount = candidate.getParameterCount();
if (parameterCount == 0) {
//通过反射实例化对象
User user3 = (User) candidate.newInstance();
System.out.println("user3:" + user3);
} else {
//模拟解析参数
ConstructorArgumentValues paramValues = beanDefinition2.getConstructorArgumentValues();
Map<Integer, ConstructorArgumentValues.ValueHolder> indexedArgumentValues = paramValues.getIndexedArgumentValues();
Object[] args0 = new Object[2];
args0[0] = indexedArgumentValues.get(0).getValue();
args0[1] = indexedArgumentValues.get(1).getValue();
//通过反射实例化对象
User user4 = (User) candidate.newInstance(args0);
System.out.println("user4:" + user4);
}
}
}
}
执行结果:
User{name='null', sex='null'}
User{name='cison', sex='男'}
user3:User{name='null', sex='null'}
user4:User{name='cison', sex='男'}
更多推荐
所有评论(0)