且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

动态注入spring bean

更新时间:2023-01-11 09:29:40

我会尽可能简化此任务。而不是在启动时有条件地加载 MyInterface 接口的一个实现,然后触发一个触发动态加载同一接口的另一个实现的事件,我将解决这个问题的不同这样,实现和维护起来要简单得多。

I would keep this task as simple as possible. Instead of conditionally load one implementation of the MyInterface interface at startup and then fire an event that triggers dynamic loading of another implementation of the same interface, I would tackle this problem in a different way, that is much simpler to implement and maintain.

首先,我只是加载所有可能的实现:

First of all, I'd just load all possible implementations:

@Component
public class MyInterfaceImplementationsHolder {

    @Autowired
    private Map<String, MyInterface> implementations;

    public MyInterface get(String impl) {
        return this.implementations.get(impl);
    }
}

这个bean只是所有实现的持有者 MyInterface 界面。这里没什么了不起的,只是常见的Spring自动装配行为。

This bean is just a holder for all implementations of the MyInterface interface. Nothing magic here, just common Spring autowiring behavior.

现在,无论你需要注入 MyInterface的特定实现 ,您可以在界面的帮助下完成:

Now, wherever you need to inject a specific implementation of MyInterface, you could do it with the help of an interface:

public interface MyInterfaceReloader {

    void changeImplementation(MyInterface impl);
}

然后,对于需要通知的每个班级更改实现,只需使其实现 MyInterfaceReloader 接口。例如:

Then, for every class that needs to be notified of a change of the implementation, just make it implement the MyInterfaceReloader interface. For instance:

@Component
public class SomeBean implements MyInterfaceReloader {

    // Do not autowire
    private MyInterface myInterface;

    @Override
    public void changeImplementation(MyInterface impl) {
        this.myInterface = impl;
    }
}

最后,你需要一个实际改变实现的bean在每个具有 MyInterface 作为属性的bean中:

Finally, you need a bean that actually changes the implementation in every bean that has MyInterface as an attribute:

@Component
public class MyInterfaceImplementationUpdater {

    @Autowired
    private Map<String, MyInterfaceReloader> reloaders;

    @Autowired
    private MyInterfaceImplementationsHolder holder;

    public void updateImplementations(String implBeanName) {
        this.reloaders.forEach((k, v) -> 
            v.changeImplementation(this.holder.get(implBeanName)));
    }
}

这只是自动装配所有实现 MyInterfaceReloader 接口并使用新实现更新每个实现,该实现从持有者检索并作为参数传递。同样,常见的Spring自动装配规则。

This simply autowires all beans that implement the MyInterfaceReloader interface and updates each one of them with the new implementation, which is retrieved from the holder and passed as an argument. Again, common Spring autowiring rules.

每当你想要改变实现时,你应该只调用 updateImplementations 带有新实现的bean名称的方法,该类是较低的驼峰案例类的简单名称,即 myImplA myImplB 用于类 MyImplA MyImplB

Whenever you want the implementation to be changed, you should just invoke the updateImplementations method with the name of the bean of the new implementation, which is the lower camel case simple name of the class, i.e. myImplA or myImplB for classes MyImplA and MyImplB.

您还应该在启动时调用此方法,以便在实现 MyInterfaceReloader 接口的每个bean上设置初始实现。

You should also invoke this method at startup, so that an initial implementation is set on every bean that implements the MyInterfaceReloader interface.