在这种情况下,我已经看到了一些关于SO的问题,但这并不是我想要的。当您没有依赖项时,SpringBoot非常适合DI。但是,没有关于如何将第三方类注入到Spring托管bean中的示例。例如,请查看下面的代码:
@ServerEndpoint(value = "/resources")
class WebSocketController
{
// This is contructed injected, but not shown here for brevity
private ApplicationContext context;
private RequestFacade facade = context.getBean(RequestFacade.class);
@OnMessage
void handleMessage(Session session)
{
// Here session is a 3rd party library object
facade.handleNewRequest(session)
}
}
@Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
@Component
class CallSession
{
private Session session;
CallSession(Session session)
{
this.session = session;
}
public void setSession(Session session)
{
// this should be called after construction of object when using Solution 2
this.session = session;
}
public void start()
{
if (this.session == null)
throw new IllegalStateException("Session is not set");
}
}
@Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
@Component
class RequestFacade
{
// This is contructed injected, but not shown here for brevity
private ApplicationContext context;
public void handleNewRequest(Session session)
{
// Solution 1:
// Require a new CallSession object for evey request
// This won't compile since session is not managed by SpringBoot
CallSession callSession = context.getBean(CallSession.class, session);
callSession.start()
// Solution 2:
// Alternate would be to use this, but I am not a fan of this because the CallSession
// is in invalid state after construction. Because devs could forget to call callSession.setSession(session)
CallSession callSession = context.getBean(CallSession.class);
callSession.setSession(session);
callSession.start();
}
}
此处Session
中传递的WebSocketController
对象是第三方对象。 CallSession
的功能需要此功能。因此,理想情况下,这应该在构造函数中传递。 CallSession
是范围原型的SpringBoot管理对象。实例化CallSession
时,除非Session
由SpringBoot管理,否则我们不能将Session
作为构造函数arg传递。
因此,替代解决方案(在RequestFacade.handleNewRequest()
方法中标记为解决方案2)无需任何构造函数arg即可构造CallSession
。然后确保通过调用CallSession.setSession()
来设置会话。我认为这不是最好的设计,因为如果Session
的运行需要CallSession
,则应在构造过程中提供它,以防止CallSession
处于无效状态。使用解决方案2时,我可以通过断言CallSession
为空并抛出适当的异常来检查session
是否处于非法状态。但是正如我之前提到的,这对我来说似乎不正确。
所以我有3个问题:
-当您的SpringBoot Beans
之一在构造中需要第3方对象时,如何进行干净的设计?
-我的构造({解决方案2)CallSession
是否没有args,并且在构造后立即通过了必要的args并在处理反模式之前检查对象状态?如果是,如何解决此问题?
-当您需要为新请求(CallSession
实例化新的RequestFacade.handleNewRequest
时,如何在不使用SCOPE_PROTOTYPE
的情况下实例化范围类型为ApplicationContext
的bean? (我读过,使用ApplicationContext
是反模式DI)
编辑:与结束语中提到的不同,此问题与此不同。在该问题中,自动有线bean不接受构造函数arg(在我们的示例中为session
)。关闭问题时请注意。请花点时间阅读和理解内容,然后再盲目地进行报告。