如何调试 Guice class/method 拦截器?

How to debug Guice class/method interceptors?

我正在尝试使用 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;
    }
}

向导设置:

    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);
}

问题:

为什么会这样?

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

这里有几个问题:

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

要调试 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;
    }
}