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