Spring源码之BeanDefinition类分析

27次阅读

共计 5310 个字符,预计需要花费 14 分钟才能阅读完成。

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 的面纱,其实并没有我们想象中的那么神秘。至于各属性的详细使用和注意事项,后续会有单独的文章来解析,尽情期待!

正文完
 0