Guice 配置错误没有实现被绑定

Guice Configuration Error No implementation was bound

我试图让一个单独的 AmazonSNS 来访问 SNS。我已经为 SNS 编写了一个模块(目前只添加了一个 SNS)和一个访问器来发布消息。我的代码如下:

public class SNSModule extends AbstractModule {

    @Override
    protected void configure() {
    }

    @Provides
    @Named("PSSNSRegionName")
    private Regions getPSSNSRegionName(
            @Named(BeanConstants.P_S_SNS_REGION) final String regionName) {
        return Regions.fromName(regionName);
    }

    @Provides
    @Singleton
    @Named(BeanConstants.P_S_SNS)
    public AmazonSNS getPSSNS(
            @NonNull @Named("PaymentSuccessSNSRegionName") final Regions region,
            final Config config) {
        return AmazonSNSClientBuilder.standard()
                .withCredentials(new AWSCredentialsProviderImpl(config.getSnsMaterialSet()))
                .withRegion(region)
                .build();
    }

}

SNS访问器如下:

@RequiredArgsConstructor(access = AccessLevel.PUBLIC, onConstructor = @__(@Inject))
public class SNSAccessor {

    @Named(BeanConstants.P_S_SNS)
    private final AmazonSNS snsClient;
    private static final String COLON = ":";
    private static final short ARN_LENGTH = 6;

    public PublishResult publishToSNS(@NonNull final String snsTopicArn, @NonNull final String messageToPublish) {
        try {
            String[] arnParts = snsTopicArn.split(COLON);
            Preconditions.checkArgument(
                    snsTopicArn.split(COLON).length == ARN_LENGTH,
                    "Expected arn to have 6 parts but found: " + arnParts.length
            );
            return snsClient.publish(snsTopicArn, messageToPublish);
        } catch (InternalErrorException e) {
            log.error("InternalErrorException publishing notification to SNS", e);
            throw new RetriableException(e);
        } catch (Exception e) {
            log.error("Exception publishing notification to SNS", e);
            throw new NonRetriableException(e);
        }
    }
}

我能够构建包,但它在运行时抛出了 ConfigurationException。

Caused by: com.google.inject.ConfigurationException: Guice configuration errors:

1) No implementation for com.amazonaws.services.sns.AmazonSNS was bound.
  while locating com.amazonaws.services.sns.AmazonSNS
    for parameter 0 at com.xyz.service.sns.SNSAccessor.<init>(SNSAccessor.java:29)

你能帮我弄清楚我做错了什么吗?我已经在 main 中正确安装了 SNSModule。

您在 SNSModule 中映射和绑定的配置看起来是正确的。

因为您还没有发布主应用程序 class 代码。 我怀疑您可能错过了在 SNSModule 上创建注入器的机会。在 main-application-class 中添加以下行:

Injector injector = Guice.createInjector(SNSModule);

Lombok 的 @RequiredArgsConstructor with onConstructor 选项不适用于带注释的依赖项注入。您需要为这种情况显式编写构造函数。

解决方案非常棘手,下面的示例项目对我有用。
龙目岛 1.8.4 Guice 4.2.2

您应该创建自己的注释并用它替换@Named 注释 见 BindingAnnotations
例如

package org.company.PSSNS

import com.google.inject.BindingAnnotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@BindingAnnotation
@Target({PARAMETER,METHOD,FIELD})
@Retention(RUNTIME)
public @interface PSSNS {}

然后添加一个lombok.config文件见here

在文件中添加以下行

lombok.copyableAnnotations += org.company.PSSNS

在你的 class

@RequiredArgsConstructor(access = AccessLevel.PUBLIC, onConstructor = @__(@Inject))
public class SNSAccessor {

    @PSSNS
    private final AmazonSNS snsClient;
    private static final String COLON = ":";
    private static final short ARN_LENGTH = 6;

同样在Guice模块中替换它

public class SNSModule extends AbstractModule {


    @Provides
    @Singleton
    @PSSNS
    public AmazonSNS getPSSNS(
            @NonNull @Named("PaymentSuccessSNSRegionName") final Regions region,
            final Config config) {
        return AmazonSNSClientBuilder.standard()
                .withCredentials(new AWSCredentialsProviderImpl(config.getSnsMaterialSet()))
                .withRegion(region)
                .build();
    }

}

当我测试需要从 maven 清理构建时

查看生成的 class 并确认您可以在构造函数中看到它。
这应该允许 Guice 注入所有构造函数参数。

默认情况下,Lombok 不会将字段上的任何注释复制到构造函数参数。如果你想继续使用 @RequiredArgsConstructor(access = AccessLevel.PUBLIC, onConstructor = @__(@Inject)),那么在你的 lombok.config 文件中添加相同的配置,如下所示:

lombok.copyableAnnotations += com.google.inject.name.Named