如何配置 Bean 原型作用域提供程序以在创建 Bean 时使用会话信息?



每次访问代理以获取实例时,我需要根据会话信息提供 bean。我该怎么做?

现在我尝试了以下方法。例如:

第一个类定义会话范围的 Bean。

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class BeanSession implements Serializable {
private Serializable rootState;
public <T extends Serializable> T getRootState() {
return (T) rootState;
}
public void setRootState(Serializable rootState) {
this.rootState = rootState;
}
}

第二类具有一些与其域相关的逻辑,并且还知道如何提供信息。Bean 必须每次都创建,因为信息可能会在线程处理期间更改。因此,每次Attribute1被访问时,我一定会得到带有新鲜信息的豆子。

@Service
public class Attribute1Service {
@Resource
private BeanSession beanSession;
public void setDefaultValue() {
Configuration configuration = beanSession.getRootState();
configuration.getAttribute1().setValue("VALUE 1");
}
@Bean
public Attribute1 attribute1() {
Configuration configuration = beanSession.getRootState();
return configuration.getAttribute1();
}
}

最后,第三个类将attribute1声明为执行其自身逻辑的依赖项。

@Service
public class Attribute2Service {
@Resource
private BeanSession beanSession;
@Resource
private Processor processor;
@Resource
private Attribute1 attribute1;
public void defineAttribute2() {
Configuration configuration = beanSession.getRootState();
String value = processor.getValue(configuration, attribute1);
configuration.getAttribute2().setValue(value);
}
public void defineAttribute3() {
Configuration configuration = beanSession.getRootState();
String value = processor.getValue(configuration, attribute1);
configuration.getAttribute3().setValue(value);
}
}

但是,问题是在创建过程中attribute1我收到以下错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'Attribute2Service': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'attribute1' defined in class path resource [Attribute1Service.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [String]: Factory method 'attribute1' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.beanSession': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:324) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
...

我不想从beanSessionAttribute2Service访问attribute1信息,因为这会在信息提供者和消费者之间建立硬耦合。

异常说明了一切 - 您的 attribute1 bean 在应用程序初始化期间创建(通过会话范围的 bean(,但没有线程绑定到请求。您还应该代理您的属性 1 Bean,因为您要将其注入到单例(属性 2 服务。

基于Alexander.Furer给出的见解。我创建了自己的作用域,并管理它以调用 bean 提供程序,以便在每次访问Attribute1方法时都有新鲜的 bean。

为此,我扩展了以下范围:

// Register scope as "runtime"
public class RuntimeScope implements Scope {
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
return objectFactory.getObject();
}
...
}

新的Attribute1服务:

@Service
public class Attribute1Service {
@Resource
private BeanSession beanSession;
public void setDefaultValue() {
Configuration configuration = beanSession.getRootState();
configuration.getAttribute1().setValue("VALUE 1");
}
@Bean
@Scope(value = "runtime", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Attribute1 attribute1() {
Configuration configuration = beanSession.getRootState();
return configuration.getAttribute1();
}
}

消费者Attribute2服务:

@Service
public class Attribute2Service {
@Resource
private BeanSession beanSession;
@Resource
private Processor processor;
@Resource
private Attribute1 attribute1;
public void defineAttribute2() {
Configuration configuration = beanSession.getRootState();
String value = processor.getValue(configuration, attribute1.getValue()); // Will call Attribute1 service to require the fresh bean
configuration.getAttribute2().setValue(value);
}
public void defineAttribute3() {
Configuration configuration = beanSession.getRootState();
String value = processor.getValue(configuration, attribute1.getValue()); // Will call Attribute1 service to require the fresh bean
configuration.getAttribute3().setValue(value);
}
}

我没有看到的问题是 Attribute1 应该是处理 bean 实例化的代理。因此,创建我自己的范围我可以保证访问attribute1(由Attribute2Service使用attribute1.getValue()(方法将创建一个新的bean(由Attribute1Service提供(。

最新更新