前言
上次我們已經(jīng)聊過(guò)了BeanDefinition的實(shí)現(xiàn)原理瘪松,以及設(shè)計(jì)思路和如何使用它。
spring工廠中使用的bean實(shí)例就是BeanDefinition.
這次的主題就是如何將BeanDefinition進(jìn)行注冊(cè)宪迟,這次要分析的接口是:BeanDefinitionRegistry
類圖
以BeanDefinitionRegistry為中心,展開的類圖:
源碼分析
BeanDefinitionRegistry
/**
*
* Spring的核心實(shí)現(xiàn)是 DefaultListableBeanFactory 和 GenericApplicationContext
*
* @author Juergen Hoeller
* @since 26.11.2003
* @see org.springframework.beans.factory.config.BeanDefinition
* @see AbstractBeanDefinition
* @see RootBeanDefinition
* @see ChildBeanDefinition
* @see DefaultListableBeanFactory
* @see org.springframework.context.support.GenericApplicationContext
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see PropertiesBeanDefinitionReader
*/
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();
boolean isBeanNameInUse(String beanName);
}
AliasRegistry這個(gè)接口的意思是可以給BeanDefinition起個(gè)別名交惯,然后注冊(cè)使用次泽。
spring 提供給了我們一個(gè)簡(jiǎn)單的類進(jìn)行測(cè)試--SimpleBeanDefinitionRegistry
SimpleBeanDefinitionRegistry
public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "'beanName' must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
this.beanDefinitionMap.put(beanName, beanDefinition);
}
//其他代碼省略
}
它僅僅使用了Map進(jìn)行了存儲(chǔ)。
可以做個(gè)小實(shí)驗(yàn)試一下:
public class Test {
public static void main(String[] args) throws Exception {
BeanDefinitionRegistry beanDefinitionRegistry = new SimpleBeanDefinitionRegistry();
AnnotatedGenericBeanDefinition genericBeanDefinition = new AnnotatedGenericBeanDefinition(Test.class);
beanDefinitionRegistry.registerBeanDefinition("springBean",genericBeanDefinition);
System.out.println(beanDefinitionRegistry.isBeanNameInUse("springBean"));
}
}
輸出:
true
DefaultListableBeanFactory
spring 推薦給我們商玫,DefaultListableBeanFactory和GenericApplicationContext才是核心箕憾。
我們看一下DefaultListableBeanFactory:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
@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 oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
this.frozenBeanDefinitionNames = null;
}
this.beanDefinitionMap.put(beanName, beanDefinition);
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
//其他方法省略
}
可以看出來(lái)它依然使用了Map進(jìn)行存儲(chǔ)(變量是beanDefinitionMap),只不過(guò)驗(yàn)證流程比較縝密了拳昌。
GenericApplicationContext
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
private ResourceLoader resourceLoader;
private boolean refreshed = false;
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
//其他代碼省略
}
看到構(gòu)造方法中的this.beanFactory = new DefaultListableBeanFactory(); 就發(fā)現(xiàn)袭异,其實(shí)GenericApplicationContext使用的注冊(cè)bean依然是使用DefaultListableBeanFactory的實(shí)現(xiàn)原理。