gpt4 book ai didi

Spring:注入(inject)bean取决于上下文( session /网络或本地线程/后台进程)

转载 作者:行者123 更新时间:2023-12-04 12:14:08 24 4
gpt4 key购买 nike

是否可以创建一个工厂或代理来决定线程是在(Web)请求还是后台进程(即调度程序)中运行,然后根据该信息创建 session bean 或原型(prototype) bean?

示例(伪 Spring 配置 :)

<bean id="userInfoSession" scope="session" />
<bean id="userInfoStatic" scope="prototype" />

<bean id="currentUserInfoFactory" />

<bean id="someService" class="...">
<property name="userInfo" ref="currentUserInfoFactory.getCurrentUserInfo()" />
</bean>

我希望这能让我的问题更容易理解......

我的解决方案

更新自己的问题永远不会太晚;)。我用两个不同的客户端 session 实例解决了这个问题,一个 SessionScoped 客户端 session 和一个 SingletonScoped session 。两个都是普通的 bean 。
<bean id="sessionScopedClientSession" class="com.company.product.session.SessionScopedClientSession" scope="session">
<aop:scoped-proxy />
</bean>

<bean id="singletonScopedClientSession" class="com.company.product.session.SingletonScopedClientSession" />

<bean id="clientSession" class="com.company.product.session.ClientSession">
<property name="sessionScopedClientSessionBeanName" value="sessionScopedClientSession" />
<property name="singletonScopedClientSessionBeanName" value="singletonScopedClientSession" />
</bean>

ClientSession 然后将决定是单例还是 session 范围:
private IClientSession getSessionAwareClientData() {
String beanName = (isInSessionContext() ? sessionScopedClientSessionBeanName : singletonScopedClientSessionBeanName);
return (IClientSession) ApplicationContextProvider.getApplicationContext().getBean(beanName);
}

可以通过以下方式收集 session 类型:
private boolean isInSessionContext() {
return RequestContextHolder.getRequestAttributes() != null;
}

所有的类都实现了一个名为 IClientSession 的接口(interface)。 singletonScoped 和 sessionScoped bean 都是从找到实现的 BaseClientSession 扩展而来的。

然后每个服务都可以使用客户端 session ,即:
@Resource
private ClientSession clientSession;

...

public void doSomething() {
Long orgId = clientSession.getSomethingFromSession();
}

现在,如果我们更进一步,我们可以为 session 编写类似模拟器之类的东西。这可以通过初始化单例 session 的 clientSession(在没有请求的上下文中)来完成。现在所有服务都可以使用相同的 clientSession,我们仍然可以“模拟”一个用户,即:
        clientSessionEmulator.startEmulateUser( testUser );
try {
service.doSomething();
} finally {
clientSessionEmulator.stopEmulation();
}

还有一个建议:注意 SingletonScoped clientSession 实例中的线程!哇,我以为我可以用更少的行来做到这一点;)如果您想了解更多关于这种方法的信息,请随时与我联系。

最佳答案

我创建了一个小的通用解决方法来注入(inject) bean 取决于上下文。

猜猜我们有两个 bean :

<bean class="xyz.UserInfo" id="userInfo" scope="session" />
<bean class="xyz.UserInfo" id="userInfoSessionLess" />

例如,我们希望将“userInfo”bean 用于 Web 用户操作,将“userInfoSessionLess”bean 用于后台服务。
Wa 也想写代码,不想考虑上下文,例如:
@Autowired
//You will get "java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request?" for session less services.
//We can fix it and autowire "userInfo" or "userInfoSessionLess" depends on context...
private UserInfo userInfo;

public save(Document superSecureDocument) {
...
superSecureDocument.lastModifier = userInfo.getUser();
...
}

现在我们需要创建自定义 session 范围以使其工作:
public class MYSessionScope extends SessionScope implements ApplicationContextAware {
private static final String SESSION_LESS_POSTFIX = "SessionLess";
private ApplicationContext applicationContext;
public Object get(String name, ObjectFactory objectFactory) {
if (isInSessionContext()) {
log.debug("Return session Bean... name = " + name);
return super.get(name, objectFactory);
} else {
log.debug("Trying to access session Bean outside of Request Context... name = " + name + " return bean with name = " + name + SESSION_LESS_POSTFIX);
return applicationContext.getBean(name.replace("scopedTarget.", "") + SESSION_LESS_POSTFIX);
}
}
private boolean isInSessionContext() {
return RequestContextHolder.getRequestAttributes() != null;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}

注册新范围:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="mySession">
<bean class="com.galantis.gbf.web.MYSessionScope" />
</entry>
</map>
</property>
</bean>

现在我们需要像这样修改 bean 定义:
<bean class="xyz.UserInfo" id="userInfo" scope="mySession" autowire-candidate="true"/>
<bean class="xyz.UserInfo" id="userInfoSessionLess" autowire-candidate="false"/>

就这样。如果我们在实际 Web 请求线程之外使用 bean,则名称为“SessionLess”的 bean 将用于所有“mySession”范围的 bean。

关于Spring:注入(inject)bean取决于上下文( session /网络或本地线程/后台进程),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3940168/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com