簡體   English   中英

Spring - 在運行時注冊scoped bean

[英]Spring - register scoped bean at runtime

我正在開發一個基於Spring的應用程序,它注冊一個自定義范圍“任務” 我們的想法是,當一個新的Task啟動時,Spring應該提供任務范圍的對象。

該任務在運行時中實例化。 它以Properties對象的形式提供了一些配置。 我想在ApplicationContext注冊該對象,但是在任務范圍內,以便該范圍內的所有bean都可以引用該特定任務的配置。

這是代碼中的粗略思想:

public class MyTask extends SourceTask {
    @Override
    public void start(Map<String, String> props) {
        context = ContextProvider.getApplicationContext();
        // Initialize the scope
        ConnectorTaskScope scope = context.getBean(ConnectorTaskScope.class);
        scope.startNewTask();

        // TODO register the props object in the context

        // get an object which requires the properties and work with it
        context.getBean(SomeScopedBean.class);        
    }
}

我無法弄清楚如何在適當范圍內的ApplicationContext中注冊bean。

謝謝

更新:

這里有一些代碼可以更好地解釋這個問題。 SomeScopedBean應該使用bean提供的配置做一些事情,看起來像這樣:

public class SomeScopedBean {
    @Autowire
    public SomeScopedBean (Properties configuration) {
        // do some work with the configuration 
    }
}

應用程序的想法是它應該有多個MyTask實例以不同的配置運行,每個任務都是自己的范圍。 在每個任務的范圍內,應該有1個使用任務配置初始化的SomeScopedBean實例。

public class MyApplication {
    public static void main (String[] args) {
        // ...
        Properties config1 = loadConfiguration1();
        Properties config2 = loadConfiguration2();
        MyTask task1 = new MyTask();
        MyTask task2 = new MyTask();
        task1.start(config1);
        task2.start(config2);
        // ...
    }
}

如果我接受你的最后評論:

我想要的是在每個范圍內(每個MyTask中)有一個SomeScopedBean實例,但每個配置有不同的配置屬性(部署框架在實例化每個Task時提供,

特別是within each MyTask ,如果它僅限於MyTask

您可以:

  • SomeScopedBean定義為原型bean
  • 創建一個工廠@Configuration ,它將使用提供的屬性配置實例化SomeScopedBean

首先是配置:

@Configuration
public class SomeScopedBeanFactoryConfiguration {

    @Bean
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public SomeScopedBean create(Properties configuration) {
        return new SomeScopedBean(configuration);
    }

}

然后將SomeScopedBeanFactoryConfiguration裝入MyTask並創建SomeScopedBean

public class MyTask extends SourceTask {

    @Autowired
    private SomeScopedBeanFactoryConfiguration  someScopedBeanFactoryConfiguration;

    @Override
    public void start(Map<String, String> props) {
        SomeScopedBean scopedBean = someScopedBeanFactoryConfiguration.create(props);    
    }
}

注意:如果必須在具有task / thread范圍的多個bean中注入SomeScopedBean ,則可以將其范圍更改為線程范圍1,例如:

    @Bean
    @Scope("thread")
    public SomeScopedBean create(Properties configuration) {
        return new SomeScopedBean(configuration);
    }
AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();

MyTask instance = new MyTask();
beanFactory.autowireBean(instance);
beanFactory.initializeBean(instance, MyTask.class.getCanonicalName());

//for singleton I used
((ConfigurableListableBeanFactory)beanFactory).registerSingleton(MyTask.class.getCanonicalName(), instance);

在你的情況下,我會注冊MyTask Proxy的單例。 代理可以保留所有與范圍相關的實例(例如,在Map或ThreadLocal存儲中)和調用委托邏輯,以便從Map中更正一個。

更新:實際上你不是自動裝配MyTask bean而是代理。 代理包裝了所有MyTask方法。 Proxy具有與MyTask相同的接口。 假設您調用ProxyMyTask.do()方法。 代理攔截調用,獲取某種范圍,例如Tread Scope示例中的當前線程,並從Map(或ThreadLocal存儲的Thread Scope)獲取MyTask的正確實例。 最后調用找到的MyTask實例的do(0方法)。

更新2:請參閱示例http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html您可以輕松地包裝界面。 您確定范圍和返回正確實例的邏輯應該在方法中

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    return method.invoke(target, args);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM