有没有办法获取提供者(或其他方式)中注入(inject)某些内容的类?这是用于日志记录的——当我的 SqlDatabase
执行某些操作时,我希望它以使用它的类的名称显示在日志中。我能想到的最好的方法是获取堆栈跟踪并向后查看它的使用位置,但我真的宁愿在注入(inject)时执行此操作。
提出问题的另一种方式是:我需要找到注入(inject)站点 - 找到 @Inject
注释的确切类 - 以创建注入(inject)类的实例。
最佳答案
我可以想到两种选择:
- 声明绑定(bind)时使用
@Provides
方法 - 使用Guice AOP这样您就可以记录实际的方法执行情况
这是两种方法的简单示例:
package stackoverflowscrapbook;
import java.util.logging.Logger;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.matcher.Matchers;
public class TestLogInjectedClassName {
interface SqlDatabase {
void doSomething();
}
static class SqlDatabaseImpl implements SqlDatabase {
public void doSomething() {
System.out.println("foo");
}
}
static class AlternativeImpl implements SqlDatabase {
public void doSomething() {
System.out.println("bar");
}
}
class Module extends AbstractModule {
@Provides
SqlDatabase database(SqlDatabaseImpl sqlDatabase) {
Logger.getLogger(TestLogInjectedClassName.Module.class.getName())
.info("Providing " + sqlDatabase.getClass());
return sqlDatabase;
}
@Override
protected void configure() {
//TODO: other bindings
}
}
class AlternativeModule extends AbstractModule {
@Provides
SqlDatabase database(AlternativeImpl sqlDatabase) {
Logger.getLogger(TestLogInjectedClassName.Module.class.getName())
.info("Providing " + sqlDatabase.getClass());
return sqlDatabase;
}
@Override
protected void configure() {
//TODO: other bindings
}
}
/**
* Just log
*/
class LoggingInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
Logger.getLogger(getClass().getName()).info(methodInvocation.getStaticPart().toString());
return methodInvocation.proceed();
}
}
/**
* Binds an interceptor on any method of any class implementing SqlDatabase
*/
class AopModule extends AbstractModule {
@Override
protected void configure() {
bindInterceptor(Matchers.subclassesOf(SqlDatabase.class), Matchers.any(), new LoggingInterceptor());
}
}
@Test
public void test() {
Injector injector = Guice.createInjector(new Module());
injector.getInstance(SqlDatabase.class);
Injector anotheInjector = Guice.createInjector(new AlternativeModule());
anotheInjector.getInstance(SqlDatabase.class);
}
@Test
public void testAop() {
Injector aopInjector = Guice.createInjector(new AopModule(), new Module());
aopInjector.getInstance(SqlDatabase.class).doSomething();
Injector alterntiveAopInjector = Guice.createInjector(new AopModule(), new AlternativeModule());
alterntiveAopInjector.getInstance(SqlDatabase.class).doSomething();
}
}
当我运行 test()
时,这是我的控制台
Dec 10, 2017 9:12:15 AM stackoverflowscrapbook.TestLogInjectedClassName$Module database
INFO: Providing class stackoverflowscrapbook.TestLogInjectedClassName$SqlDatabaseImpl
Dec 10, 2017 9:12:15 AM stackoverflowscrapbook.TestLogInjectedClassName$AlternativeModule database
INFO: Providing class stackoverflowscrapbook.TestLogInjectedClassName$AlternativeImpl
当我运行 testAop()
时,这是我的控制台。请注意,在这种情况下,我们会记录注入(inject)和方法的执行。您可以通过删除 @Provides
方法中的日志来选择仅记录执行情况。另请注意,只有当 Guice 创建 SqlDatabase
实例并且其实现中的方法不是最终时,这才有可能。 (我没有格式化下面的日志代码,因为预览中的行被截断了)
2017 年 12 月 10 日上午 9:14:01 stackoverflowscrapbook.TestLogInjectedClassName$Module 数据库 信息:提供类 stackoverflowscrapbook.TestLogInjectedClassName$SqlDatabaseImpl$$EnhancerByGuice$$d7a0782d 2017 年 12 月 10 日上午 9:14:01 stackoverflowscrapbook.TestLogInjectedClassName$LoggingInterceptor 调用 信息:公共(public)无效 stackoverflowscrapbook.TestLogInjectedClassName$SqlDatabaseImpl.doSomething() 富 2017 年 12 月 10 日上午 9:14:01 stackoverflowscrapbook.TestLogInjectedClassName$AlternativeModule 数据库 信息:提供类 stackoverflowscrapbook.TestLogInjectedClassName$AlternativeImpl$$EnhancerByGuice$$3ef8fbf1 2017 年 12 月 10 日上午 9:14:01 stackoverflowscrapbook.TestLogInjectedClassName$LoggingInterceptor 调用 信息:公共(public)无效 stackoverflowscrapbook.TestLogInjectedClassName$AlternativeImpl.doSomething() 酒吧
关于java - 如何在 guice 提供程序中获取绑定(bind)目标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47683465/