【问题标题】:How to debug Guice class/method interceptors?如何调试 Guice 类/方法拦截器?
【发布时间】:2020-08-27 16:12:43
【问题描述】:

我正在尝试使用 guice-persist,但无法让它在简单的测试用例中工作。这是一个从调度程序调用的通用请求处理程序:

public abstract class TransactionAwareRequestHandler<T> extends SyncRequestHandler<T> {

    @Transactional // Guice should make sure I get a transaction here
    public final Object handleRequest(T request) {
        return handleRequestWithTx(request);
    }

    public abstract Object handleRequestWithTx(T request);
}

我的测试处理程序是:

public static class TestHandler extends TransactionAwareRequestHandler {
    @Override
    public Object handleRequestWithTx(Object request) {
        SessionFactory sessionFactory = injector.getProvider(SessionFactory.class).get();
        assertTrue(sessionFactory.getCurrentSession().getTransaction().isActive()); // <<<--- Fails here!
        return null;
    }
}

Guice 设置:

    injector = Guice.createInjector(
        new HibernatePersistModule()
    );

这将为所有带有@Transactional注解的类和方法添加一个绑定拦截器

测试用例:

@Test
public void shouldRunInTransaction() throws RequestHandlerException {
    TestHandler handler = injector.getInstance(TestHandler.class);
    
    // I'm not getting a proxy here! Why???
    assertTrue("Expected proxy: " + handler.getClass(),
            Proxy.isProxyClass(handler.getClass()));
    
    handler.handleRequest(null);
}

问题:

为什么会这样?

如何调试它以找出它发生的原因?有什么方法可以将日志记录添加到类/方法匹配器中?

【问题讨论】:

  • 我认为这是因为 Guice 根本不检查继承的方法。当我将自己的方法拦截器放在那里时,我可以看到 Guice 不会尝试将拦截器与 TransactionAwareRequestHandler.handleRequest 匹配。只有TestHandler.handleRequestWithTx 显示在调试输出中。这是为什么呢?
  • 您不能将@Annotations 应用于最终类或方法(也不能应用于私有,尽管这不是问题)。
  • 嗯...好点。我只是希望 Guice 给我一个错误或警告。

标签: guice interceptor guice-persist


【解决方案1】:

这里有几个问题:

  1. Java 无法创建最终类或方法的代理。在这种情况下,Guice 应该给出错误或警告,但由于某种原因,它没有。
  2. 注释不在类上,而是在超类上。标准方法匹配器只考虑类的方法。如果你想要不同的行为,你需要这个匹配器:https://stackoverflow.com/a/61674578/34088

要调试 Guice 正在做什么,请将匹配器包装在一个执行日志记录的设备中:

import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.matcher.Matcher;

public class MatcherLogger<T> extends AbstractMatcher<T> {

    private final Matcher<T> delegate;
    private final Logger log;
    
    public MatcherLogger(Matcher<T> delegate) {
        this(delegate, LoggerFactory.getLogger(MatcherLogger.class));
    }

    public MatcherLogger(Matcher<T> delegate, Logger log) {
        this.delegate = Objects.requireNonNull(delegate);
        this.log = Objects.requireNonNull(log);
    }
    
    @Override
    public boolean matches(T t) {
        boolean result = delegate.matches(t);
        log.debug("matches {} for {}", result, t);
        return result;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    相关资源
    最近更新 更多