[英]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.