一、需求產生原因:
通過修改Spring容器中對象中某個屬性,該對象被spring其他服務調用,可以動態實現調用方實現不同的業務邏輯。
二、涉及spring相關對象:
- DefaultListableBeanFactory:IOC容器始祖
默認實現了ListableBeanFactory和BeanDefinitionRegistry接口,基於bean definition對象,是一個成熟的bean factroy。
最典型的應用是:在訪問bean前,先注冊所有的definition(可能從bean definition配置文件中)。使用預先建立的bean定義元數據對象,從本地的bean definition表中查詢bean definition因而將不會花費太多成本。
DefaultListableBeanFactory既可以作為一個單獨的beanFactory,也可以作為自定義beanFactory的父類。
三、關於其部分內部方法:
1.getBean():獲取容器中對象
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
return this.doGetBean(name, requiredType, (Object[])null, false);
}
public Object getBean(String name, Object... args) throws BeansException {
return this.doGetBean(name, (Class)null, args, false);
}
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) throws BeansException {
return this.doGetBean(name, requiredType, args, false);
}
2. removeBeanDereference():刪除bean對象定義
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
Assert.hasText(beanName, "'beanName' must not be empty");
BeanDefinition bd = (BeanDefinition)this.beanDefinitionMap.remove(beanName);
if (bd == null) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("No bean named '" + beanName + "' found in " + this);
}
throw new NoSuchBeanDefinitionException(beanName);
} else {
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames);
updatedDefinitions.remove(beanName);
this.beanDefinitionNames = updatedDefinitions;
}
} else {
this.beanDefinitionNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
this.resetBeanDefinition(beanName);
}
}
3.registerBeanDefinition():重新注冊bean定義
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 var9) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
}
}
BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
}
if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
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 (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if (this.hasBeanCreationStarted()) {
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;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
} else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || this.containsSingleton(beanName)) {
this.resetBeanDefinition(beanName);
}
}
四、主要實現方法
方法解讀
- 先判斷容器中是否包含該對象
- 包含則刪除該對象
- 生成Bean定義生成器(BeanDefinitionBuilder),此處會默認調用該對象的無參構造方法,用於注入該實例。
- 通過生成器生成BeadDefinition;
- 然后設定部分BeadDefinition部分屬性參數,其他默認
- 通過方法重寫初始化注入該對象
- 工具方法
/**
* 動態注入對象
* @param beanName bean對象名稱
* @param beanClass bean對象class類型
*/
private void dynamicInjectionObj(String beanName, Class<?> beanClass) {
boolean containsBean = defaultListableBeanFactory.containsBean(beanName);
if (containsBean) {
defaultListableBeanFactory.removeBeanDefinition(beanName);
}
//默認使用對象的無參構造方法:此對象已經重寫無參構造(此處會重新實例化一個新對象)
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(beanClass);
//構造注入對象參數
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
beanDefinition.setAutowireMode(2);
beanDefinition.setPrimary(true);
beanDefinition.setSynthetic(true);
// beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
beanDefinition.setScope("singleton");
beanDefinition.setRole(0);
defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinition);
}