理解spring的BeanDefinition和配置文件(原文标题:动态注册bean到spring容器)
2014-01-16 17:59
776 查看
spring通过Resource接口读取配置文件信息,将BeanDefinition和<bean>标签中的信息对应起来,比如scope属性,另外MutablePropertyValues就是配置文件中的一系列property标签,下面的一篇文章我认为说的很清楚。
附上部分源码:
(原文标题:动态注册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了,如果没有,就继续以下的步骤:
整个过程非常简单,其中注意一个地方,就是MutablePropertyValues和spring配置文件的关系。一个beandefinition的MutablePropertyValues就是配置文件中的一系列property标签,可以获取其中的value。如果property是一个bean,那个获取过来的Object对象,是BeanDefinitionHolder对象,就是对属性中引用bean的定义,以此类推。
比如,spring的配置文件里面有这样的bean定义:
那么通过getPropertyValues()方法获取到的MutablePropertyValues就包含两个属性,可以通过MutablePropertyValues的getPropertyValue(“p1″)获取到test这个值,getPropertyValue(“p2″)获取到的就是x.y.z.B这个类对应的beandefinition。
附上部分源码:
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> |
相关文章推荐
- Spring源码阅读--BeanDefinition 在 IOC 容器中的注册
- spring技术内幕笔记:IoC容器的初始化过程(3)- BeanDefinition的注册
- Spring源码解析-BeanDefinition在IOC容器中的注册(三)
- 通过DefaultListableBeanFactory加载.xml配置文件学习Spring-IoC容器注册/加载bean的机制(源码走读)
- spring 根据配置文件动态注册bean
- spring 技术内幕--IOC初始化之BeanDefinition的在IOC容器中的注册
- Spring源码学习--Spring配置文件解析BeanDefinitionDocumentReader(三)
- Spring源码学习--Spring配置文件解析BeanDefinitionReader(二)
- 【Spring源码--IOC容器的实现】(四)BeanDefinition的注册
- (spring-第8回【IoC基础篇】)BeanDefinition在IoC容器中的注册
- Spring源码阅读之IoC容器初始化3 -- BeanDefinition在IoC容器中的注册
- 死磕Spring系列之二,bean标签的解析和BeanDefinition的注册
- Spring源码解析--Spring配置文件解析BeanDefinitionParserDelegate(四)
- SpringBoot源码分析之BeanDefinitionLoader注册主Configuration的Java配置类
- Spring图解将bean标签转换BeanDefinition
- org.springframework.beans.factory.BeanDefinitionStoreException: Unrecognized xbean element mapping: beans in namespace h
- (spring-第5回【IoC基础篇】)spring容器从加载配置文件到实例化bean的内部工作机制
- (spring-第6回【IoC基础篇】)BeanDefinition——实例化Bean之前的第一大利器。
- Spring源码之旅(3)_BeanDefinition的解析与注册
- 【Spring Framework 深入】—— IoC容器初始化 -> BeanDefinition的注册