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已注册。