Can I replace a Spring bean definition at runtime?

后端 未结 11 1354
萌比男神i
萌比男神i 2020-11-30 17:44

Consider the following scenario. I have a Spring application context with a bean whose properties should be configurable, think DataSource or MailSender

相关标签:
11条回答
  • 2020-11-30 18:12

    You should have a look at JMX. Spring also provides support for this.

    • Spring 2.0.x
    • Spring 2.5.x
    • Spring 3.0.x
    0 讨论(0)
  • 2020-11-30 18:16

    Option 1 :

    1. Inject the configurable bean into the DataSource or MailSender. Always get the configurable values from the configuration bean from within these beans.
    2. Inside the configurable bean run a thread to read the externally configurable properties (file etc..) periodically. This way the configurable bean will refresh itself after the admin had changed the properties and so the DataSource will get the updated values automatically.
      • You need not actually implement the "thread" - read : http://commons.apache.org/configuration/userguide/howto_filebased.html#Automatic_Reloading

    Option 2 (bad, i think, but maybe not - depends on use case) :

    1. Always create new beans for beans of type DataSource / MailSender - using prototype scope. In the init of the bean, read the properties afresh.

    Option 3 : I think, @mR_fr0g suggestion on using JMX might not be a bad idea. What you could do is :

    1. expose your configuration bean as a MBean (read http://static.springsource.org/spring/docs/2.5.x/reference/jmx.html)
    2. Ask your admin to change the configuration properties on the MBean (or provide an interface in the bean to trigger property updates from their source)
    3. This MBean (a new piece of java code that you will need to write), MUST keep references of Beans (the ones that you want to change / inject the changed properties into). This should be simple (via setter injection or runtime fetch of bean names / classes)
      1. When the property on the MBean is changed (or triggered), it must call the appropriate setters on the respective beans. That way, your legacy code does not change, you can still manage runtime property changes.

    HTH!

    0 讨论(0)
  • 2020-11-30 18:16

    You may want to have a look at the Spring Inspector a plug-gable component that provides programmatic access to any Spring based application at run-time. You can use Javascript to change configurations or manage the application behaviour at run-time.

    0 讨论(0)
  • 2020-11-30 18:25

    This is not something I tried, I am trying to provide pointers.

    Assuming your application context is a subclass of AbstractRefreshableApplicationContext(example XmlWebApplicationContext, ClassPathXmlApplicationContext). AbstractRefreshableApplicationContext.getBeanFactory() will give you instance of ConfigurableListableBeanFactory. Check if it is instance of BeanDefinitionRegistry. If so you can call 'registerBeanDefinition' method. This approach will be tightly coupled with Spring implementation,

    Check the code of AbstractRefreshableApplicationContext and DefaultListableBeanFactory(this is the implementation you get when you call 'AbstractRefreshableApplicationContext getBeanFactory()')

    0 讨论(0)
  • 2020-11-30 18:25

    Here is the nice idea of writing your own PlaceholderConfigurer that tracks the usage of properties and changes them whenever a configuration change occurs. This has two disadvantages, though:

    1. It does not work with constructor injection of property values.
    2. You can get race conditions if the reconfigured bean receives a changed configuration while it is processing some stuff.
    0 讨论(0)
  • 2020-11-30 18:26

    I can think of a 'holder bean' approach (essentially a decorator), where the holder bean delegates to holdee, and it's the holder bean which is injected as a dependency into other beans. Nobody else has a reference to holdee but the holder. Now, when the holder bean's config is changed, it recreates the holdee with this new config and starts delegating to it.

    0 讨论(0)
提交回复
热议问题