Google Tomcat 8.5 下的 Guice MethodInterceptor
Google Guice MethodInterceptor under Tomcat 8.5
我们不想在 tomcat 8.5 下使用使用 guice 作为提供程序的 aop 方法拦截器。我们目前已经在 Java-FX 应用程序中使用拦截器和 guice,没有任何问题。
尝试在 Tomcat 下做同样的事情是行不通的。对象通过 guice 注入到 servlet 中,但这些对象的注释方法未绑定到拦截器。看起来 guice 可能认为 cglib/asm 不可用并恢复为 none-aop.
为了使用 guice 的 aop,servlet 容器是否需要满足任何特殊的先决条件?如上所述,guice/cglib/asm 的相同配置在 none webapp 项目中适用于我们。
@Singleton
public class TestServlet extends HttpServlet {
@Inject
X x;
public TestServlet() {
System.out.println("constructor");
try {
throw new IOException();
} catch (final Exception e) {
e.printStackTrace();
}
}
@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp)
throws ServletException, IOException {
testMethod(resp);
}
protected void testMethod(final HttpServletResponse resp) throws IOException {
x.test(resp);
}
}
我们不希望 servlet 中的 X 包含被拦截的方法。
通过将 throw/catch 放在构造函数中,我们验证了构造函数是通过 guice 调用的。
public class X {
@Y
public int test(final ServletResponse res) throws IOException {
res.getWriter().write("123");
return 1;
}
}
public class TestInterceptor implements MethodInterceptor {
@Override
public Object invoke(final MethodInvocation arg0) throws Throwable {
System.out.println("METHOD INTERCEPTOR " + arg0);
return arg0.proceed();
}
}
public class Module extends AbstractModule {
@Override
protected void configure() {
System.out.println("TestInterceptor configuration");
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Y.class), new TestInterceptor());
}
}
@WebListener
public class BootStrap extends GuiceServletContextListener {
...
@Override
protected Injector getInjector() {
final Injector inject = Guice.injector(new Module(), new ServletModule() {
@Override
protected void configureServlets() {
super.configureServlets();
System.out.println("Injector");
serve("/test2/*").with(TestServlet.class);
}
});
return inject;
}
}
servlet 可访问且 X 为 none-null 但在调试器中查看它很明显没有进行二进制代码修改。
我们是不是漏掉了什么?任何人都可以 link 一个工作指南的例子 (4+)/tomcat (8+)/aop 例子吗?
编辑
原来是和servlet容器无关。问题出在 guice 本身。很抱歉造成混淆,这个问题很难解决。
对于那些感兴趣的人,我们开了一个问题
https://github.com/google/guice/issues/1094
请注意,在撰写本文时,这还没有被视为错误。也可能是我们误解了 javadoc。
我之前将 Guice AOP 与 Tomcat 一起使用(尽管它是 Tomcat 的旧版本)并且 AOP 有效。 (我不能 link 因为它是专有代码)。
我在查看您发布的代码时注意到的一件事是您没有使用 GuiceFilter,我认为这是必需的。
如前所述 here 您需要在 web.xml 的顶部配置它,如下所示:
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
根据评论编辑:
您不必 modify/hack 类加载器就可以在 servlet 容器中使用 Guice 拦截器。它们应该开箱即用,无需额外更改。
我们不想在 tomcat 8.5 下使用使用 guice 作为提供程序的 aop 方法拦截器。我们目前已经在 Java-FX 应用程序中使用拦截器和 guice,没有任何问题。
尝试在 Tomcat 下做同样的事情是行不通的。对象通过 guice 注入到 servlet 中,但这些对象的注释方法未绑定到拦截器。看起来 guice 可能认为 cglib/asm 不可用并恢复为 none-aop.
为了使用 guice 的 aop,servlet 容器是否需要满足任何特殊的先决条件?如上所述,guice/cglib/asm 的相同配置在 none webapp 项目中适用于我们。
@Singleton
public class TestServlet extends HttpServlet {
@Inject
X x;
public TestServlet() {
System.out.println("constructor");
try {
throw new IOException();
} catch (final Exception e) {
e.printStackTrace();
}
}
@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp)
throws ServletException, IOException {
testMethod(resp);
}
protected void testMethod(final HttpServletResponse resp) throws IOException {
x.test(resp);
}
}
我们不希望 servlet 中的 X 包含被拦截的方法。 通过将 throw/catch 放在构造函数中,我们验证了构造函数是通过 guice 调用的。
public class X {
@Y
public int test(final ServletResponse res) throws IOException {
res.getWriter().write("123");
return 1;
}
}
public class TestInterceptor implements MethodInterceptor {
@Override
public Object invoke(final MethodInvocation arg0) throws Throwable {
System.out.println("METHOD INTERCEPTOR " + arg0);
return arg0.proceed();
}
}
public class Module extends AbstractModule {
@Override
protected void configure() {
System.out.println("TestInterceptor configuration");
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Y.class), new TestInterceptor());
}
}
@WebListener
public class BootStrap extends GuiceServletContextListener {
...
@Override
protected Injector getInjector() {
final Injector inject = Guice.injector(new Module(), new ServletModule() {
@Override
protected void configureServlets() {
super.configureServlets();
System.out.println("Injector");
serve("/test2/*").with(TestServlet.class);
}
});
return inject;
}
}
servlet 可访问且 X 为 none-null 但在调试器中查看它很明显没有进行二进制代码修改。
我们是不是漏掉了什么?任何人都可以 link 一个工作指南的例子 (4+)/tomcat (8+)/aop 例子吗?
编辑
原来是和servlet容器无关。问题出在 guice 本身。很抱歉造成混淆,这个问题很难解决。 对于那些感兴趣的人,我们开了一个问题 https://github.com/google/guice/issues/1094
请注意,在撰写本文时,这还没有被视为错误。也可能是我们误解了 javadoc。
我之前将 Guice AOP 与 Tomcat 一起使用(尽管它是 Tomcat 的旧版本)并且 AOP 有效。 (我不能 link 因为它是专有代码)。
我在查看您发布的代码时注意到的一件事是您没有使用 GuiceFilter,我认为这是必需的。
如前所述 here 您需要在 web.xml 的顶部配置它,如下所示:
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
根据评论编辑: 您不必 modify/hack 类加载器就可以在 servlet 容器中使用 Guice 拦截器。它们应该开箱即用,无需额外更改。