Resource
Resource
代表一个资源,可以是文件、类路径上的文件、URL 等。它提供了对资源的抽象和访问方法。BeanDefinition
BeanDefinition
是 Spring 中描述和管理 Bean 配置的核心概念,它包括了有关 Bean 的信息,如类名、作用域、依赖关系、初始化方法等,而 AnnotatedBeanDefinitionReader
的主要任务之一是将使用注解配置的类转化为 BeanDefinition
并注册到 Spring 容器中。PropertiesBeanDefinitionReader
是 Spring 框架的一个组件,它的主要功能是从属性文件中加载 Bean 的配置信息,然后将这些配置信息解析并转化为 Spring 容器中的 Bean 定义。属性文件的格式通常是键值对,键表示 Bean 的名称,值表示 Bean 的类名或其他配置属性。这个过程允许我们将 Bean 配置与应用程序代码和 XML 配置文件分离,以实现动态加载和管理 Bean 定义,增强了应用程序的可扩展性和配置的灵活性。
PropertiesBeanDefinitionReader
通过 loadBeanDefinitions(Resource resource)
方法加载属性文件,其中的 Resource
可以是文件路径、类路径或其他资源标识符,指定了包含 Bean 定义信息的属性文件的位置。PropertiesBeanDefinitionReader
会解析文件中的内容,识别 Bean 的名称、类名以及其他配置属性。PropertiesBeanDefinitionReader
创建相应的 BeanDefinition
对象,其中包含了 Bean 的定义信息,包括名称、类、属性、依赖关系等。PropertiesBeanDefinitionReader
将解析得到的 Bean 定义注册到 Spring IOC 容器中,使这些 Bean 可以在应用程序中被实例化和使用。我们创建了一个 Spring Bean 工厂(DefaultListableBeanFactory
)和一个属性文件读取器(PropertiesBeanDefinitionReader
),然后从属性文件中加载 Bean 的定义,然后通过 Bean 工厂获取相应的 Bean 对象,以实现动态加载和管理 Bean 配置
public class PropertiesBeanDefinitionReaderDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(beanFactory);
// 从properties文件加载bean定义
reader.loadBeanDefinitions(new ClassPathResource("bean-definitions.properties"));
// 获取bean
System.out.println("myBean = " + beanFactory.getBean("myBean"));
System.out.println("myBean = " + beanFactory.getBean("myBean"));
}
}
属性文件 "bean-definitions.properties
" 中的内容如下:
myBean.(class)=com.xcs.spring.bean.MyBean
myBean.message=hello world
myBean.(lazy-init)=true
myBean.(scope)=prototype
MyBean
的Java类,代表了一个简单的Java Bean。
public class MyBean {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "MyBean{" +
"message='" + message + '\'' +
", hashCode='0x" + Integer.toHexString(System.identityHashCode(this)).toUpperCase() + '\'' +
'}';
}
}
运行结果发现,我们从属性文件中动态加载 Bean 配置,同时控制懒加载和作用域,以实现更灵活的 Bean 管理。在这个场景中,每次请求 "myBeanA
" 都会得到一个新的实例,这是因为作用域设置为 "prototype
"。
myBean = MyBean{message='hello world', hashCode='0x6646153'}
myBean = MyBean{message='hello world', hashCode='0x45DD4EDA'}
在org.springframework.beans.factory.support.PropertiesBeanDefinitionReader#loadBeanDefinitions(resource)
方法中,又调用 loadBeanDefinitions(encodedResource,prefix)
方法来实际加载 Bean 定义。
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource), null);
}
在org.springframework.beans.factory.support.PropertiesBeanDefinitionReader#loadBeanDefinitions(encodedResource,prefix)
方法中,主要是从属性文件中加载和管理 Bean 配置,实现了 Spring 中属性文件的解析和注册。
public int loadBeanDefinitions(EncodedResource encodedResource, @Nullable String prefix)
throws BeanDefinitionStoreException {
// 如果启用了跟踪级别的日志,则输出加载属性文件的日志信息
if (logger.isTraceEnabled()) {
logger.trace("Loading properties bean definitions from " + encodedResource);
}
// 创建 Properties 对象,用于存储属性文件中的键值对配置
Properties props = new Properties();
try {
try (InputStream is = encodedResource.getResource().getInputStream()) {
// 如果指定了编码,使用指定编码读取属性文件
if (encodedResource.getEncoding() != null) {
getPropertiesPersister().load(props, new InputStreamReader(is, encodedResource.getEncoding()));
}
// 否则,使用默认编码读取属性文件
else {
getPropertiesPersister().load(props, is);
}
}
// 注册 Bean 定义,将属性文件中的配置转化为 Bean 定义并注册到容器中
int count = registerBeanDefinitions(props, prefix, encodedResource.getResource().getDescription());
// 如果启用了调试级别的日志,则输出已加载的 Bean 定义数量的日志信息
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + encodedResource);
}
return count;
}
catch (IOException ex) {
// 处理异常,如果在读取或注册过程中发生异常,抛出 BeanDefinitionStoreException 异常
throw new BeanDefinitionStoreException("Could not parse properties from " + encodedResource.getResource(), ex);
}
}
在org.springframework.beans.factory.support.PropertiesBeanDefinitionReader#registerBeanDefinitions(map, prefix,resourceDescription)
方法中,首先遍历属性文件中的键值对配置,根据配置的前缀以及键的格式,将合法的 Bean 定义注册到容器中。如果键不符合要求或已经注册,则会忽略。最终,该方法返回已注册的 Bean 定义数量,用于跟踪注册的 Bean 数量。
public int registerBeanDefinitions(Map<?, ?> map, @Nullable String prefix, String resourceDescription)
throws BeansException {
if (prefix == null) {
prefix = "";
}
int beanCount = 0;
// 遍历属性文件中的键值对配置
for (Object key : map.keySet()) {
if (!(key instanceof String)) {
throw new IllegalArgumentException("Illegal key [" + key + "]: only Strings allowed");
}
String keyString = (String) key;
if (keyString.startsWith(prefix)) {
// 键的格式为:prefix<名称>.属性
String nameAndProperty = keyString.substring(prefix.length());
// 查找属性名之前的点号,忽略属性键中的点号。
int sepIdx ;
int propKeyIdx = nameAndProperty.indexOf(PropertyAccessor.PROPERTY_KEY_PREFIX);
if (propKeyIdx != -1) {
sepIdx = nameAndProperty.lastIndexOf(SEPARATOR, propKeyIdx);
}
else {
sepIdx = nameAndProperty.lastIndexOf(SEPARATOR);
}
if (sepIdx != -1) {
String beanName = nameAndProperty.substring(0, sepIdx);
if (logger.isTraceEnabled()) {
logger.trace("Found bean name '" + beanName + "'");
}
if (!getRegistry().containsBeanDefinition(beanName)) {
// 如果还未注册该 Bean...
// 注册 Bean 定义
registerBeanDefinition(beanName, map, prefix + beanName, resourceDescription);
++beanCount;
}
}
else {
// 忽略该键:它不是有效的 Bean 名称和属性,
// 尽管它以所需的前缀开始。
if (logger.isDebugEnabled()) {
logger.debug("Invalid bean name and property [" + nameAndProperty + "]");
}
}
}
}
// 返回已注册的 Bean 定义数量
return beanCount;
}
在org.springframework.beans.factory.support.PropertiesBeanDefinitionReader#registerBeanDefinition(beanName,map,prefix, resourceDescription)
方法中,主要是处理属性文件中的配置并将其转化为 Spring Bean 定义,然后注册到容器中。
protected void registerBeanDefinition(String beanName, Map<?, ?> map, String prefix, String resourceDescription)
throws BeansException {
// ... [代码部分省略以简化]
try {
AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(
parent, className, getBeanClassLoader());
bd.setScope(scope);
bd.setAbstract(isAbstract);
bd.setLazyInit(lazyInit);
bd.setConstructorArgumentValues(cas);
bd.setPropertyValues(pvs);
getRegistry().registerBeanDefinition(beanName, bd);
}
catch (ClassNotFoundException ex) {
throw new CannotLoadBeanClassException(resourceDescription, beanName, className, ex);
}
catch (LinkageError err) {
throw new CannotLoadBeanClassException(resourceDescription, beanName, className, err);
}
}
PropertiesBeanDefinitionReader
来动态加载 Bean 定义,从而使应用程序的配置更加灵活。这样,应用程序可以根据需要动态配置和管理 Bean。PropertiesBeanDefinitionReader
可以用来加载这些配置文件,并将配置信息转化为 Spring 的 Bean 定义。PropertiesBeanDefinitionReader
?
PropertiesBeanDefinitionReader
需要创建一个实例并与 Spring 的 Bean 工厂(如 DefaultListableBeanFactory
)结合使用。然后,使用 loadBeanDefinitions
方法加载属性文件中的配置,并将 Bean 定义注册到容器中。lazy-init
和 scope
来配置懒加载和作用域。例如,myBean.(lazy-init)=true
可以配置一个 Bean 为懒加载,而 myBean.(scope)=prototype
可以配置 Bean 的作用域为原型。myBeanA=(class)=com.example.MyBean
中的 Bean 名称是 "myBeanA"。PropertiesBeanDefinitionReader
?
PropertiesBeanDefinitionReader
可以使应用程序更加灵活,允许我们将配置信息从代码中分离出来,从而实现应用程序的可配置性。它还支持动态加载和管理 Bean,适用于需要动态配置的场景。此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。