Java:使用 Spring 自动装配的库与 Guice 程序
Java: Use a Spring Autowired library with Guice program
我有一个我一直在开发的服务器。它使用 Guice 作为 DI。我需要使用一个团队库。它使用 @Autowired 作为它的 DI。
我的代码
import team.requiredlibrary.NeededClass
public class MyClass extends NeededClass {
@Inject
public MyClass() {
}
}
导入库
public class NeededClass {
@Autowired
private NestedClass1 nestedClass1;
@Autowired
private NestedClass2 nestedClass2;
}
运行时,nestedClass1 和 nestedClass2 为空。
我在这里有什么选择。有没有办法让 Guice 识别@Autowired?如果可以选择用@Inject 替换@Autowired 来更新团队库,那么这项工作会那么简单并且值得付出努力吗?假设最坏的情况,我会在我的 DI 项目中用 Spring 替换 Guice 吗?
Spring 支持 @Inject
,因此如果可以在您的团队库中将 @Autowired
替换为 @Inject
一切都应该没问题。
否则,您可以为 guice 创建一个自定义注入器,请参阅此 link:https://github.com/google/guice/wiki/CustomInjections
您可以为 @Autowired
创建自定义注入器,并使用 TypeListener
类型 TypeEncounter
的方法 getProvider(Class)
获取可用于检索的提供程序所需的类型。
当然,您必须正确配置 Guice 才能注入这些类型。
这种方法的问题:您可能不会涵盖 Spring 支持的所有内容,例如。 G。 @Qualifier
注释。
这是一个工作示例:
public class AutowiredTypeListener implements TypeListener {
public <I> void hear(TypeLiteral<I> typeLiteral, TypeEncounter<I> typeEncounter) {
Class<?> clazz = typeLiteral.getRawType();
while (clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
Autowired annotation = field.getAnnotation(Autowired.class);
if (annotation != null) {
typeEncounter.register(new AutowiredMembersInjector<I>(field,
typeEncounter.getProvider(field.getType())));
}
}
clazz = clazz.getSuperclass();
}
}
}
public class AutowiredMembersInjector<T> implements MembersInjector<T> {
private final Field field;
private final Provider<?> instanceProvider;
public AutowiredMembersInjector(Field field, Provider<?> instanceProvider) {
this.field = field;
this.instanceProvider = instanceProvider;
field.setAccessible(true);
}
public void injectMembers(T t) {
try {
field.set(t, instanceProvider.get());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
然后只需在您的 Guice 模块中添加 bindListener(Matchers.any(), new AutowiredTypeListener());
。
我直接注意到 @Autowired
支持可选注入,这似乎是不可能的,因为一旦使用 typeEncounter
创建了提供者,就需要绑定 class已注册。
我有一个我一直在开发的服务器。它使用 Guice 作为 DI。我需要使用一个团队库。它使用 @Autowired 作为它的 DI。
我的代码
import team.requiredlibrary.NeededClass
public class MyClass extends NeededClass {
@Inject
public MyClass() {
}
}
导入库
public class NeededClass {
@Autowired
private NestedClass1 nestedClass1;
@Autowired
private NestedClass2 nestedClass2;
}
运行时,nestedClass1 和 nestedClass2 为空。
我在这里有什么选择。有没有办法让 Guice 识别@Autowired?如果可以选择用@Inject 替换@Autowired 来更新团队库,那么这项工作会那么简单并且值得付出努力吗?假设最坏的情况,我会在我的 DI 项目中用 Spring 替换 Guice 吗?
Spring 支持 @Inject
,因此如果可以在您的团队库中将 @Autowired
替换为 @Inject
一切都应该没问题。
否则,您可以为 guice 创建一个自定义注入器,请参阅此 link:https://github.com/google/guice/wiki/CustomInjections
您可以为 @Autowired
创建自定义注入器,并使用 TypeListener
类型 TypeEncounter
的方法 getProvider(Class)
获取可用于检索的提供程序所需的类型。
当然,您必须正确配置 Guice 才能注入这些类型。
这种方法的问题:您可能不会涵盖 Spring 支持的所有内容,例如。 G。 @Qualifier
注释。
这是一个工作示例:
public class AutowiredTypeListener implements TypeListener {
public <I> void hear(TypeLiteral<I> typeLiteral, TypeEncounter<I> typeEncounter) {
Class<?> clazz = typeLiteral.getRawType();
while (clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
Autowired annotation = field.getAnnotation(Autowired.class);
if (annotation != null) {
typeEncounter.register(new AutowiredMembersInjector<I>(field,
typeEncounter.getProvider(field.getType())));
}
}
clazz = clazz.getSuperclass();
}
}
}
public class AutowiredMembersInjector<T> implements MembersInjector<T> {
private final Field field;
private final Provider<?> instanceProvider;
public AutowiredMembersInjector(Field field, Provider<?> instanceProvider) {
this.field = field;
this.instanceProvider = instanceProvider;
field.setAccessible(true);
}
public void injectMembers(T t) {
try {
field.set(t, instanceProvider.get());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
然后只需在您的 Guice 模块中添加 bindListener(Matchers.any(), new AutowiredTypeListener());
。
我直接注意到 @Autowired
支持可选注入,这似乎是不可能的,因为一旦使用 typeEncounter
创建了提供者,就需要绑定 class已注册。