BeanDefinitionRegistry
摘要
見名知義,BeanDefinitionRegistry就是用于將BeanDefinition注冊(cè)到spring容器中,即添加到beanDefinitionMap(Map<String, BeanDefinition>)。
類圖

源碼分析
BeanDefinitionRegistry是一個(gè)接口,定義了一系列對(duì)BeanDefinition的操作接口,如注冊(cè)、移除、返回等等,需要各子類實(shí)現(xiàn)BeanDefinition注冊(cè)的動(dòng)作。
/**
* Interface for registries that hold bean definitions, for example RootBeanDefinition
* and ChildBeanDefinition instances. Typically implemented by BeanFactories that
* internally work with the AbstractBeanDefinition hierarchy.
*
* <p>This is the only interface in Spring's bean factory packages that encapsulates
* <i>registration</i> of bean definitions. The standard BeanFactory interfaces
* only cover access to a <i>fully configured factory instance</i>.
*
* <p>Spring's bean definition readers expect to work on an implementation of this
* interface. Known implementors within the Spring core are DefaultListableBeanFactory
* and GenericApplicationContext.
*/
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
//用于檢測(cè)beanName是否已經(jīng)被其他BeanDefinition使用
boolean isBeanNameInUse(String beanName);
可以看到BeanDefinitionRegistry下有三個(gè)實(shí)現(xiàn)類:
SimpleBeanDefinitionRegistry
這個(gè)Registry是spring提供的給用戶測(cè)試,寫demo的實(shí)現(xiàn),很簡(jiǎn)單,這個(gè)不多討論。
GenericApplicationContext
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { ... }
GenericApplicationContext分別繼承了AbstractApplicationContext和實(shí)現(xiàn)了BeanDefinitionRegistry
繼承AbstractApplicationContext為后續(xù)的各種ApplicationContext的實(shí)現(xiàn)子類提供了統(tǒng)一父類,而BeanDefinitionRegistry的實(shí)現(xiàn)則是由DefaultListableBeanFactory來(lái)完成。
DefaultListableBeanFactory
我們將著重分析一下DefaultListableBeanFactory中的registerBeanDefinition實(shí)現(xiàn)。
@Override
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) {
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 {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
//下面這一段這樣處理的目的是為了訪問全局變量在多線程訪問的情況下,出現(xiàn)迭代的同時(shí)對(duì)list進(jìn)行修改,會(huì)導(dǎo)致ConcurrentModificationException
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
- 首先對(duì)BeanDefinition進(jìn)行有效性校驗(yàn), validate()判斷hasMethodOverrides和getFactoryMethodName不能同時(shí)存在。
lookup-method 和 replaced-method 注解標(biāo)注的方法都會(huì)被保存在methodOverrides 集合中,當(dāng)bean在實(shí)例化時(shí)如果檢測(cè)到有methodOverrides存在,則會(huì)動(dòng)態(tài)為當(dāng)前bean生成代理并使用對(duì)應(yīng)攔截器對(duì)bean進(jìn)行增強(qiáng)。
public void validate() throws BeanDefinitionValidationException {
if (hasMethodOverrides() && getFactoryMethodName() != null) {
throw new BeanDefinitionValidationException(
"Cannot combine static factory method with method overrides: " +
"the static factory method must create the instance");
}
if (hasBeanClass()) {
prepareMethodOverrides();
}
}
FactoryMethod則是一種通過工廠方法創(chuàng)建bean的一種方式,分為靜態(tài)工廠方法和動(dòng)態(tài)工廠方法
//靜態(tài)工廠,不需要實(shí)例化工廠本身,通過靜態(tài)方法創(chuàng)建bean
<bean id="beanA" class="com.xxx.FactoryA" factory-method="createA"></bean>
//動(dòng)態(tài)工廠,需要實(shí)例化工廠,根據(jù)工廠bean來(lái)創(chuàng)建需要的bean
<bean id="factoryA" class="com.xxx.Factory"></bean>
<bean id="beanA" factory-bean="factoryA" factory-method="createA"></bean>
- 通過判斷該beanName是否已經(jīng)存在。
a. 已經(jīng)存在BeanDefinition,先判斷是否允許覆蓋,允許則輸出一系列日志,put新的beanDefinition
b. 如果不存在,先判斷是否已經(jīng)有bean被創(chuàng)建過,即是否已經(jīng)進(jìn)入運(yùn)行階段。如果還是啟動(dòng)注冊(cè)階段,可以直接put,否則就需要加鎖。
DefaultListableBeanFactory源碼分析將重點(diǎn)分析BeanFactory的一系列實(shí)現(xiàn)。