相關文章java
大多數的方法都能從它的名字知道它是幹啥的、都能在 XML 配置文件中找到對應的配置項緩存
大部分的實現是落在 AbstractBeanDefinition 中、裏面的邏輯也並非特別的複雜、畢竟只是一些 get/set 方法架構
對於它的三個子類 GenericBeanDefinition RootBeanDefinition ChildBeanDefinition 其實本質上來講、它們並沒有太大的區別、它們都繼承了 AbstractBeanDefinition 、在它們各自的類中、並無什麼太大的特殊的邏輯、某種程度上來講、它們能夠說是差異很是小的框架
咱們在 Spring 容器初始化的時候、讀取 XML 配置文件並註冊 BeanDefinition 、這個BeanDefinition 是子類中的哪一個類呢ide
// 解釋 bean 標籤的時候
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
複製代碼
public static AbstractBeanDefinition createBeanDefinition( @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
if (className != null) {
if (classLoader != null) {
bd.setBeanClass(ClassUtils.forName(className, classLoader));
}
else {
bd.setBeanClassName(className);
}
}
return bd;
}
複製代碼
最終它會落到這個工具類裏面、建立的都是 GenericBeanDefinition工具
而在 BeanDefinitionRegistry 的實現類中、都是如此存儲的post
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
複製代碼
咱們也是可使用其餘的 BeanDefinition 的子類註冊ui
而咱們在 getBean 的流程中的時候、當咱們沒法在三級緩存中獲取到 bean 的時候、就開始了建立 bean 的流程、這個時候、就要從 beanDefinition 中獲取相關信息建立 beanthis
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
複製代碼
咱們能夠在 AbstractBeanFactory 中找到spa
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
複製代碼
能夠看到 Map 中的 value 的類型是 RootBeanDefinition
若是你在定義中存在了父子 bean、或者更加具體的說、就是在 BeanDefinition 中、你的parentName 不爲空、做爲子 bean、你就要合成父 bean 的一些屬性
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null || mbd.stale) {
previous = mbd;
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
} else {
mbd = new RootBeanDefinition(bd);
}
} else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
......................
// Deep copy with overridden values.
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
........
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
return mbd;
}
複製代碼
貌似到目前爲止、咱們仍是沒有看到 ChildBeanDefinition 使用的場景
貌似確實沒啥用是吧在整一個 Spring 框架中、個人版本 5.2
可是呢、其實咱們能夠手動的建立一個 BeanDefiniton 註冊給 Spring
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
rootBeanDefinition.setBeanClass(Company.class);
rootBeanDefinition.getPropertyValues().add("name", "XX");
rootBeanDefinition.getPropertyValues().add("numberOfPeople", "1000");
defaultListableBeanFactory.registerBeanDefinition("rootCompany", rootBeanDefinition);
ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition("rootCompany");
defaultListableBeanFactory.registerBeanDefinition("childCompany", childBeanDefinition);
System.out.println(defaultListableBeanFactory.getBean("rootCompany"));
System.out.println(defaultListableBeanFactory.getBean("childCompany"));
System.out.println(defaultListableBeanFactory.getBean("rootCompany") == defaultListableBeanFactory.getBean("childCompany"));
複製代碼
其實在 RootBeanDefinition 和 ChildBeanDefinition 中咱們看到註釋說、其實首選是 GenericBeanDefinition 、由於 RootBeanDefinition 不可以指定 parentName、而 ChildBeanDefinition 必須有 parentName、這在使用上是很是不靈活的
或許這就是 GenericBeanDefinition 出現的緣由吧
在 AbstractAutowireCapableBeanFactory#doCreateBean 中
在建立好了一個 bean 的時候(不完整的 bean ),會對 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 進行回調、這個時候是比加入第三級緩存以前早一點
defaultListableBeanFactory.addBeanPostProcessor(new MergedBeanDefinitionPostProcessor() {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
System.out.println("beanName:" + beanName);
}
});
複製代碼