当前位置: 首页 > 知识库问答 >
问题:

Spring上下文动态变化

秦涵涤
2023-03-14

我读过动态bean定义更改。我在一个简单的代码示例中尝试了它(参见下面的代码),我发现在不想停止服务器而是添加/更改bean定义的情况下,它非常有吸引力。

问题:

public class Main {
final static String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
        "<beans xmlns=\"http://www.springframework.org/schema/beans\"\n" +
        "       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
        "       xmlns:context=\"http://www.springframework.org/schema/context\"\n" +
        "       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\">\n" +
        "    <context:annotation-config />\n" +
        "    <context:component-scan base-package=\"vbah\"/>";

final static String contextA =
        "<bean id=\"test\" class=\"java.lang.String\">\n" +
                "\t\t<constructor-arg value=\"fromContextA\"/>\n" +
                "</bean></beans>";

final static String contextB =
        "<bean id=\"test\" class=\"java.lang.String\">\n" +
                "\t\t<constructor-arg value=\"fromContextB\"/>\n" +
                "</bean></beans>";

public static void main(String[] args) throws IOException {
    //create a single context file
    final File contextFile = new File("src/resources/spring-config.xml");

    //write the first context into it
    FileUtils.writeStringToFile(contextFile, header + contextA);

    //create a spring context
    FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
            new String[]{contextFile.getPath()}
    );

    //echo "fromContextA"
    System.out.println(context.getBean("test"));

    //write the second context into it
    FileUtils.writeStringToFile(contextFile, header + contextB);

    //refresh the context
    context.refresh();

    //echo "fromContextB"
    System.out.println(context.getBean("test"));
}
}
    null

StatiCapplicationContextBeanFactoryPostProcessor都允许我在运行时更改bean定义。但有什么不同,利/弊?

共有1个答案

廉高邈
2023-03-14

这样做安全吗(见下面的代码)?

你必须定义安全。

AbstractApplicationContext#refresh()方法javadoc声明

    null

StatiCapplicationContext是您自己注册bean定义的ApplicationContext类之一。在您的示例中,从XML文件解析bean定义并在幕后注册。对于StatiCapplicationContext,可以使用RegisterBeanDefinition(..)或其他RegisterXXX()方法显式注册bean定义。

BeanFactoryPostProcessor可以访问正在使用的BeanFactory,因此可以访问所有已注册的bean定义。因此,您可以检索所需的任何BeanDefinition并对其进行修改。正如javadoc forBeanFactoryPostProcess#PostProcessBeanFactory(..)所述

所有bean定义都将被加载,但是还没有bean被实例化。这允许重写或添加属性,甚至可以对快速初始化bean进行重写或添加属性。

最后,BeanPostProcessor不会更改bean定义。您可以使用BeanPostProcessor来更改bean的创建方式,但是底层BeanDefinition将保持不变。

对于您的编辑(比实际答案大:))

据我所知,BeanPostProcess允许您在运行时通过用代理包装对象来修改已经存在的bean实例。我说的对吗?

AbstractApplicationContext#refresh()删除所有单例bean并重新创建它们。

但是如果我想改变原型/自定义作用域bean的定义呢?如果我有两个bean:A和B,A有对B的引用。如果我以不包含B定义的方式更改bean定义,那么B实例将被销毁,但不会创建新的实例。将获得null依赖项。我说的对吗?

applicationcontext中声明bean定义。如果要更改bean定义,请在BeanFactoryPostProcessor中更改它,或者在上下文配置中以不同的方式声明它。

对于依赖项,如果破坏Bbean定义,就不会有bean注入a,Spring会抱怨,抛出NosuchBeanDefinitionException。Bean注入从不注入null,除非您明确地告诉它。

StatiCapplicationContextBeanFactoryPostProcessor都允许我在运行时更改bean定义。但有什么不同,利/弊?

两者服务于完全不同的目的。StatiCapplicationContext是一个ApplicationContext实现。在这里,您声明bean定义。BeanFactoryPostProcessor用于根据您希望实现的任何条件以任何方式修改这些bean定义。

我没有用例给你。了解以上每一项都能做什么,当你得到特定的需求时,你就会知道什么时候应用它们。

 类似资料:
  • 问题内容: 我已经阅读了动态bean定义的更改。我在一个简单的代码示例中进行了尝试(请参见下面的代码),并且在不想停止服务器但添加/更改bean定义的情况下,它非常吸引人。 问题: 这样做安全吗(请参见下面的代码)? 我读过,借助or 或?可以在运行时实现bean定义更改。那么区别是什么呢? final static String header = “<?xml version="1.0" enc

  • 所以我有一个项目,在其中我使用Spring boot,并希望利用一个模块系统。我希望模块系统能够动态地重新加载。我让它几乎可以工作,但是@ComponentScan在模块中完全不工作。 有一个模块文件夹,包含启动时加载的jar文件,需要动态卸载、加载和重新加载。 模块通过AnnotationConfigApplicationContext创建,上下文的类加载器设置为核心的类加载器,模块接口中的方法

  • 请帮帮我!!我到处找了很多,找到了任何有用的信息,或者我有,但我不能在这么短的时间内测试我在web上找到的所有东西,而且spring文档似乎只对普通情况和xml配置非常好,不适合我试图做的疯狂的事情,也不适合编程配置。

  • 我将Spring Boot与Spring集成在一起,我希望为每个<code>child() 此时此刻,我正在处理这个:(只有最相关的行) 我已经查看了SpringApplication ationBuilder方法,并且属性从父亲传播到孩子: 但是我需要动态加载一些属性,如下例所示: 从此示例中提取:Spring多个 imapAdapter 这是因为一些Spring集成组件将从配置文件中动态加载。

  • 我正在为project编写集成测试,我希望在Spring将所有数据库迁移脚本导入到schema.sql之前将其合并到schema.sql中。为此,我使用了一个小类,它在项目中搜索sql文件并将它们合并为一个。我创建了一个套件,如下所示: 那么,这是我的测试: 但这并不像我想象的那样有效。看起来Spring试图运行schema.sql的速度比我创建schema.sql的速度要快,但失败如下所示: 附

  • 我有一个启用web的SpringBoot应用程序,所以我的html页面文件位于/src/main/resources/static上。 但是我每次都必须重新启动应用程序,以便查看我对该路径上的任何文件所做的更改,这是浪费时间,有人知道这个问题的“修复”吗? 谢谢…!