Spring上下文动态变化

VB_

我已经阅读了动态bean定义的更改。我在一个简单的代码示例中进行了尝试(请参见下面的代码),并且在不想停止服务器但添加/更改bean定义的情况下,它非常吸引人。

问题:

  1. 这样做安全吗(请参见下面的代码)?
  2. 我读过,借助StaticApplicationContexorBeanPostProcessorBeanFactoryPostProcessor?可以在运行时实现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"));
    }
    }
    

编辑:

您能否回答以下问题:

  1. 据我了解,BeanPostProcess您可以在运行时通过将对象与代理包装在一起来修改已存在的bean实例。我对吗?
  2. AbstractApplicationContext#refresh()删除所有单例bean并重新创建它们。

    • 但是,如果我想更改原型/自定义范围的bean的定义?
    • 如果我有两个bean:A和B。A引用了B。如果我以不包含B的定义的方式更改bean的定义。B实例将被销毁,但新实例将不被破坏。被创建。比A将获得null依赖。我对吗?
  3. StaticApplicationContext并且BeanFactoryPostProcessor都允许我在运行时改变一个bean定义。但是,优点/缺点有什么区别?

  4. [主要问题]为什么Spring有3种机制来实现相同的目标。你可以做一个简单的compoarison(或usecases例子)之间AbstractApplicationContext#refresh()StaticApplicationContextBeanFactoryPostProcessor请。
Sotirios Delimanolis

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

您必须定义safe

AbstractApplicationContext#refresh()方法的javadoc状态

由于这是一种启动方法,因此,如果失败,则应销毁已创建的单例,以避免悬挂资源。换句话说,在调用该方法之后,应实例化所有单例或根本不实例化。

基本上,您上下文中的每个bean都将被销毁,对它们的所有引用都将被删除,从而使它们成为垃圾收集的候选对象。您需要确保这些bean具有释放它们可能拥有的任何资源的适当方法。有不同的方法可以做到这一点

  • 使您的类实现该DisposableBean接口。
  • destroy-method在您的<bean>@Bean定义中添加一个属性
  • 用注释方法@PreDestroy

请注意,refresh()通常会急于刷新您的ApplicationContext,即。立即重新实例化所有咖啡豆。在这种情况下,您可能会注意到应用程序速度变慢。

我读过,借助StaticApplicationContextorBeanPostProcessorBeanFactoryPostProcessor?可以在运行时实现bean定义更改那么区别是什么呢?

StaticApplicationContextApplicationContext您自己注册Bean定义之一在您的示例中,bean定义是从XML文件中解析出来的,并在后台注册。使用StaticApplicationContext,您可以使用registerBeanDefinition(..)或其他registerXxx()方法来显式注册Bean定义。

ABeanFactoryPostProcessor可以访问BeanFactory正在使用的,因此可以访问所有已注册的bean定义。这样,您可以检索所需的任何BeanDefinition内容并对其进行修改。作为BeanFactoryPostProcess#postProcessBeanFactory(..)的javadoc

所有bean定义都将被加载,但尚未实例化任何bean。这甚至可以覆盖或添加属性,甚至可以用于初始化bean。

您可以在ApplicationContext实际使用bean定义之前对其进行更改

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


为了您的编辑(大于实际答案:))

据我了解,BeanPostProcess允许您在运行时通过将对象与代理包装在一起来修改已存在的bean实例。我对吗?

它不仅用于代理,还可以对对象进行任何操作:修改其属性,在其他上下文中注册它,将其制成null,等等。这涉及bean的定义。

AbstractApplicationContext#refresh() 放下所有单例豆并重新创建它们。

但是,如果我想更改原型/自定义范围的bean的定义?如果我有两个bean:A和B。A引用了B。如果我以不包含B的定义的方式更改bean的定义。B实例将被销毁,但新实例将不被破坏。被创建。比A将获得一个空的依赖关系。我对吗?

在中ApplicationContext,您声明了bean定义。如果要更改Bean定义,请在中对其进行更改,BeanFactoryPostProcessor或者在上下文配置中对其进行不同的声明。

对于依赖项,如果破坏了Bbean的定义,则不会注入任何bean A,Spring会抱怨,throwing NoSuchBeanDefinitionExceptionnull除非您明确告知,否则Bean注入永远不会注入

StaticApplicationContext并且BeanFactoryPostProcessor都允许我在运行时改变一个bean定义。但是,优点/缺点有什么区别?

两者的目的完全不同。StaticApplicationContext是一个ApplicationContext实现。在这里,您声明了bean定义。ABeanFactoryPostProcessor可以根据您希望实现的任何条件以任何方式修改这些Bean定义。

为什么Spring有3种机制来实现相同的目标。你能简单比较(或usecases的例子)AbstractApplicationContext#refresh()StaticApplicationContextBeanFactoryPostProcessor请。

目标是不一样的。一个ApplicationContext比一个不同的BeanFactoryPostProcessor和进场在上下文中的生命周期不同的时间(请参阅图不错你在前面的问题了)。

我没有适合您的用例。了解以上所有内容可以做什么,当您获得特定要求时,您将知道何时应用它们。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Spring上下文动态变化

来自分类Dev

Spring Boot动态上下文创建(父/子)

来自分类Dev

jQuery的变化。closest上下文?

来自分类Dev

电子:动态上下文菜单

来自分类Dev

创建动态中心上下文

来自分类Dev

JS对象文字,此上下文不断变化

来自分类Dev

以下示例中上下文的奇怪变化

来自分类Dev

如何动态地将外部定义的bean定义添加到Spring上下文?

来自分类Dev

Spring REST模拟上下文路径

来自分类Dev

Spring Boot和上下文路径

来自分类Dev

未加载Spring上下文

来自分类Dev

了解Spring MVC中的上下文

来自分类Dev

用于DelegatingFilterProxy的单独Spring上下文

来自分类Dev

Spring安全上下文,几个用户

来自分类Dev

找不到Spring Application上下文

来自分类Dev

了解Spring MVC中的上下文

来自分类Dev

Spring Integration多上下文

来自分类Dev

用于DelegatingFilterProxy的单独Spring上下文

来自分类Dev

Spring安全上下文,几个用户

来自分类Dev

Thymeleaf Spring Mail上下文错误

来自分类Dev

未加载Spring上下文

来自分类Dev

找不到Spring Application上下文

来自分类Dev

上下文之间的Spring Integration通信

来自分类Dev

spring paypal api上下文问题

来自分类Dev

Spring 测试:缺少 servlet 上下文

来自分类Dev

isGooglePlayServicesAvailable的上下文(上下文上下文)

来自分类Dev

Spring root应用程序上下文和servlet上下文混淆

来自分类Dev

从Spring安全性上下文访问应用程序上下文

来自分类Dev

重用缓存的Spring上下文以构建更大的上下文