spring通过Resource接口读取配置文件信息,将BeanDefinition和<bean>标签中的信息对应起来,比如scope属性,另外MutablePropertyValues就是配置文件中的一系列property标签,下面的一篇文章我认为说的很清楚。
附上部分源码:
package org.springframework.beans.factory.config;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
/**
* Return the property values to be applied to a new instance of the bean.
* <p>The returned instance can be modified during bean factory post-processing.
* @return the MutablePropertyValues object (never <code>null</code>)
*/
MutablePropertyValues getPropertyValues();
/**
* Return whether this a <b>Singleton</b>, with a single, shared instance
* returned on all calls.
* @see #SCOPE_SINGLETON
*/
boolean isSingleton();
boolean isPrototype();
boolean isAutowireCandidate();
//......
}
public class MutablePropertyValues implements PropertyValues, Serializable {
private final List<PropertyValue> propertyValueList;
private Set<String> processedProperties;
private volatile boolean converted = false;
/**
* Creates a new empty MutablePropertyValues object.
* <p>Property values can be added with the <code>add</code> method.
* @see #add(String, Object)
*/
public MutablePropertyValues() {
this.propertyValueList = new ArrayList<PropertyValue>(0);
}
//........
}
public class PropertyValue extends BeanMetadataAttributeAccessor implements Serializable {
private final String name;
private final Object value;
private Object source;
private boolean optional = false;
private boolean converted = false;
private Object convertedValue;
/** Package-visible field that indicates whether conversion is necessary */
volatile Boolean conversionNecessary;
/** Package-visible field for caching the resolved property path tokens */
volatile Object resolvedTokens;
/** Package-visible field for caching the resolved PropertyDescriptor */
volatile PropertyDescriptor resolvedDescriptor;
public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
//......
}
(原文标题:动态注册bean到spring容器)
拷贝地址:http://coolex.info/blog/253.html。
原先的设计是通过已有的库,将数据通过rmi写入到远程服务器;现在有需求需要将支持多个,而且是自定义的远程服务器ip。
因为整个接口原先都是通过spring配置文件,包括rmi的地址。同时,为了维护方便,不能直接将打好的jar包拿过来改,于是就采用了复制原有的bean definition,动态注册新的bean到那个spring容器中。
首先需要获取jar包中的spring容器,这里需要将applicationContext接口转换成为真正的实现:DefaultListableBeanFactory,这样才能使用其中的注册和获取beandefinition方法。
当要获取bean的时候,首先先通过beanfactory的containsBean方法判断是否已经有bean了,如果没有,就继续以下的步骤:
RootBeanDefinition remoteDataServerClientDefinition =
(RootBeanDefinition) beanFactory.getBeanDefinition(BASE_BEAN_NAME); //获取“模板”bean的定义
RootBeanDefinition remoteDataServerClientNewDefinition =
new RootBeanDefinition(remoteDataServerClientDefinition); //深度复制
MutablePropertyValues properties =
remoteDataServerClientNewDefinition.getPropertyValues(); //拿到原bean的属性
BeanDefinitionHolder defaultDataSourceFactoryDefinitionHolder = //这里获取属性值
(BeanDefinitionHolder) properties.getPropertyValue("serviceFactory").getValue();
//下面省略,主要是对属性值的修改和重新赋值
//向bean factory中注册新的bean,第一个参数是bean的名字,第二个参数是bean的定义
beanFactory.registerBeanDefinition(udasClientBeanName, remoteDataServerClientNewDefinition);
beanFactory.getBean(udasClientBeanName); //然后就可以从容器中拿bean了
整个过程非常简单,其中注意一个地方,就是MutablePropertyValues和spring配置文件的关系。一个beandefinition的MutablePropertyValues就是配置文件中的一系列property标签,可以获取其中的value。如果property是一个bean,那个获取过来的Object对象,是BeanDefinitionHolder对象,就是对属性中引用bean的定义,以此类推。
比如,spring的配置文件里面有这样的bean定义:
1
2 3 4 5 6 |
<bean id="a" class="x.y.z.A">
<property name="p1" value="test" /> <property name="p2"> <bean class="x.y.z.B" /> </propery> </bean> |
那么通过getPropertyValues()方法获取到的MutablePropertyValues就包含两个属性,可以通过MutablePropertyValues的getPropertyValue(“p1″)获取到test这个值,getPropertyValue(“p2″)获取到的就是x.y.z.B这个类对应的beandefinition。