Guice 注入 Java Web 应用程序的业务层
我已成功使用 Guice 将提供程序注入到现有 java web 应用程序的 servlet 部分,但是,我无法通过应用程序的业务层(非 servlet java 类)访问注入器。
我已经阅读了 Injecting the Injector,但对我来说,这看起来更像是一种 hack,并且在几个地方,包括 Guice 文档,它说不要做太多。
我想我的问题是,我在哪里引导 java web 应用程序,以便非 servlet/过滤器类可以访问在我用来扩展 GuiceServletContextListener 的类中创建的注入器?有什么方法可以使这些类在不注入注入器的情况下可注入吗?
谢谢您,如果您需要任何说明,请告诉我。
编辑:
到目前为止,我正在尝试使用一个简单的记录器来完成此操作 servlet,我称之为:
@Inject
private static org.slf4j.Logger log;
注入在 MyLoggerModule 中设置如下(位于 createInjector 调用 ServletModule) :
@Override
public void configure() {
bindListener(Matchers.any(), new SLF4JTypeListener()); // I
built my own SLF4JTypeListener...
}
这一切在 servlet 中都完美运行,但字段注入确实如此 当被不是 servlet 或过滤器的类调用时不起作用。
I have sucessfully used Guice to Inject Providers into the servlet portion of an existing java web application, however, I can't access the injectors through the business layer (non-servlet java classes) of the application.
I have read up on Injecting the Injector, but to me that seems more like a hack and in several places, including the Guice documentation, it says not to do that too much.
I guess my question is, Where do I bootstrap a java web app so that the non-servlet/filter classes have access to the injector created in the class I use to extend GuiceServletContextListener? Is there any way to make those classes injectable without injecting the injector?
Thank you and let me know if you need any clarification.
Edit:
I am attempting to do this with a simple logger, so far, in my
servlets, I call:
@Inject
private static org.slf4j.Logger log;
The injection is set up in MyLoggerModule as follows (which is in the
createInjector call with ServletModule) :
@Override
public void configure() {
bindListener(Matchers.any(), new SLF4JTypeListener()); // I
built my own SLF4JTypeListener...
}
This all works perfectly in the servlets, but the field injection does
not work when called by a class that is not a servlet or filter.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Guice 不会拦截对新对象的调用,因此如果您的业务层尚未使用 Guice 来创建需要注入的对象,则需要进行修改才能执行此操作。
注入仅在注入期间由 Guice 处理时才有效。因此,从您制作的基本注入器开始,您请求的实例所需的任何标有
@Inject
的内容都将由 Guice 尽可能提供,并在实例化期间提供其中,进一步的 @Inject 注释将由提供者和绑定填充,直到不需要实例化任何新内容。然而,从那时起,您将不会将字段注入到在 Guice 注入之外创建的 servlet 中,也许可以通过在某处调用new
来实现,这很可能是您的对象工厂正在做的事情。您需要更改对象工厂以使用提供程序而不是新的提供程序。如果您可以编辑这些内容,那就不会太难,因为 Guice 可以为您提供默认的绑定提供程序。
因此,您的业务层可以感知 Guice 的一种方法是,让正在创建 servlet 的任何内容首先创建一个注入器,然后请求注入器创建 servlet。如果这意味着您将有多个注入器,那么是的,这将是一个问题,但仅限于您想要成为单例的对象。因此,您可以为单例注入器创建一个工厂模式类,或者您可以找到创建 servlet 本身的这些类(此处键入 bar)的创建位置(在 foo 中),然后使用其中的注入器(在 foo 中)开始Guice 注入器创建这些(bar 类型)类并修改它们(bar 类型)以请求它们将使用的 servlet 的提供者,而不是调用新的 servlet。
现在我想到了这一点,如果对于 10-20 个 servlet 类型只发生一次或两次,那么事情可能会很简单,或者如果有一些框架定义了完全灵活的行为来确定更新的时间和原因,那么事情可能会很复杂。
另一种选择是按照建议始终避免在字段上使用 @Inject。现在,您的 servlet 将 org.slf4j.Logger 作为构造参数。该构造函数被标记为
@Inject
,并将参数的值分配给该字段。然后,任何不使用注入的地方都应该在新调用时因参数数量不正确而中断。通过弄清楚如何获取此处提供的 servlet,或者如何将 servlet 的提供者获取到类中来修复这些问题。Guice doesn't intercept calls for new objects, so if your business layer isn't already using Guice to create the objects that need injection, it'll need modification to do so.
The injection only works when handled by Guice during injection. So starting from the base injector you've made, whatever is marked with
@Inject
which is needed for the instance you've requested will be provided by Guice as best it can, and in turn, during instanciation of those, further@Inject
annotations will be filled in by providers and bindings until nothing new needs to be instanciated. From that point on however you are not going to get fields injected into servlets created outside Guice's injection, perhaps by callingnew
somewhere, which is likely what your Object Factory is doing.You'll need to change your Object Factory to use providers instead of new. If you could edit these, it wouldn't be too hard to do since Guice can give you default providers for bindings.
So one way your business layer could be Guice aware is to have whatever is creating servlets first create an Injector and then request the servlets be created by the injector. If this means you'll have more than one injector, then yes, that will be a problem but only for the objects you want to be singletons. So you could make a factory pattern class for a singleton injector, or you could find where these classes (here typed bar) which are creating servlets themselves are created (in foo), and then start with the injector there (in foo) using one Guice injector to create those (bar type) classes and also modifying them (bar type) to request a provider for the servlets which they'll use instead of making calls for a new servlet.
Now that I think about this, it could be simple if it kind of only happens once or twice for 10-20 servlet types, or it could be complicated if there's some framework that defines totally flexible behavior for what gets newed up when and why.
Another option would be avoiding @Inject on fields at all times, as recommended. So now your servlets are taking in an
org.slf4j.Logger
as a construction parameter. The constructor is marked@Inject
, and it assigns the parameter's value to the field. Then any place you're not using injection should break with an incorrect number of parameters at a new call. Fix these by figuring out how to either get the servlet provided here instead, or how to get a provider for the servlet into the class.不知道你的意思...如果你将对象注入到 servlet/过滤器中,这些对象的依赖项也会由 Guice 注入,依此类推。
您如何创建尝试将此记录器注入其中的类?它们必须由 Guice 创建才能注入,这意味着没有
new
。Not sure what you mean... if you inject objects in to your servlets/filters, those objects have their dependencies injected by Guice as well, and so on all the way down.
How are you creating the classes that you're trying to inject this logger in to? They must be created by Guice to be injected, which means no
new
.