我正在编写自己的作用域(即实现的类org.springframework.beans.factory.config.Scope
),我需要注入一些 bean。我怎么做?
背景:Spring 必须首先创建所有范围 bean,以便我可以定义哪些 bean 进入范围。但是我首先需要构建范围的 bean 呢?
我正在编写自己的作用域(即实现的类org.springframework.beans.factory.config.Scope
),我需要注入一些 bean。我怎么做?
背景:Spring 必须首先创建所有范围 bean,以便我可以定义哪些 bean 进入范围。但是我首先需要构建范围的 bean 呢?
我想出了这个似乎很安全的解决方法,但我想听听评论(或者我的回答可能会给你一些更好的想法):
@Autowired
)创建一个“范围配置器”bean:
public CustomScopeConfigurer {
@Autowired private Foo foo;
private CustomScope scope;
public CustomScopeConfigurer( CustomScope scope ) {
this.scope = scope;
}
@PostConstruct
public void initScope() {
scope.setFoo( foo );
}
}
此配置器 bean 不能是惰性的。
推理:
范围本身不能使用自动装配,因为它是在第一个 bean 之前创建的。虽然它可能会在以后创建,但您可以确定它将在所有其他 bean 之前创建。所以自动装配不能可靠地工作。
配置器 bean 将与所有其他 bean 一起创建,但在范围之后。所以自动装配会为它工作。
由于配置器 bean 不是惰性初始化的,它将在应用程序的其余部分可以看到应用程序上下文之前创建。这意味着@Scope("custom")
此时不能创建范围的任何 bean(即带有 的 bean) - 范围不能是“活动的”,但是 -> Spring 不会尝试将任何 bean 放入其中。
作用域本身通常在某处创建为静态常量。这就是为什么我们必须将它作为参数传递给构造函数。
你可以很简单地做到这一点。
考虑以下自定义范围类:
package com.way2learn;
import java.util.Map;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
public class MyCustomScope implements Scope{
private Map<String, Object> scope;
public void setScope(Map<String, Object> scope) {
this.scope = scope;
}
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
checkAndClear();
Object bean=scope.get(name);
if(bean==null){
bean=objectFactory.getObject();
scope.put(name,bean);
}
return bean;
}
private void checkAndClear() {
//Some logic to check condition and clear the scope
}
//optional methods
@Override
public Object remove(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object resolveContextualObject(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getConversationId() {
// TODO Auto-generated method stub
return null;
}
}
它依赖于java.util.Map
.
您不能自动装配使用@Autowired
它作为@Autowired
注释AutoWiredAnnotationBeanPostProcessor
仅在之后工作。
但自定义范围将在之前注册AutoWiredAnnotationBeanPostProcessor
。
因此,您可以手动注入Map
类MyCustomScope
,如下所示:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
<util:map key-type="java.lang.String" value-type="java.lang.Object" id="custScopeMap"/>
<bean id="myCustomScope" class="com.way2learn.MyCustomScope">
<property name="scope" ref="custScopeMap"/>
</bean>
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="myScope" value-ref="myCustomScope"/>
</map>
</property>
</bean>
</beans>
我尝试过这个。它工作正常。我在Aaron Digulla's
答案中发现了一个错误,即
考虑以下场景:Spring's CustomScopeConfigurer
将创建第一个 bean,立即创建CustomScope
bean,现在我们的自定义范围已准备好使用。一段时间Aaron Digulla's CustomScopeConfigurer
后将创建将 foo 初始化为CustomScope
. 但是,如果在创建 bean 之后CustomScope registration
和之前创建了一些自定义范围的 bean,会发生Aaron Digulla's CustomScopeConfigurer
什么?对于那些 bean,bean 中不会有 foo CustomScope
。