简体   繁体   English

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

[英]Guice Configuration Error No implementation was bound

I am trying to keep a singleton AmazonSNS to access an SNS.我正在尝试保留一个单例 AmazonSNS 来访问 SNS。 I have written a module for SNS (only one SNS is added currently) and an accessor to publish the message.我已经为 SNS 编写了一个模块(目前只添加了一个 SNS)和一个用于发布消息的访问器。 My code is as follows:我的代码如下:

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

}

The SNS Accessor is as follows: 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);
        }
    }
}

I was able to build the package but it threw ConfigurationException at runtime.我能够构建包,但它在运行时抛出了 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)

Could you please help me figure out what I am doing wrong?你能帮我弄清楚我做错了什么吗? I have installed the SNSModule in main correctly.我已经在 main 中正确安装了 SNSModule。

Lombok's @RequiredArgsConstructor with onConstructor option does not work with the annotated dependency injections. Lombok 的带有onConstructor选项的@RequiredArgsConstructor不适用于带注释的依赖项注入。 You need to write a constructor explicitly for this case.您需要为这种情况显式编写构造函数。

The configurations that you are mapping and binding in SNSModule looks correct.您在 SNSModule 中映射和绑定的配置看起来是正确的。

Since you have not posted the main application class code.由于您尚未发布主应用程序类代码。 I suspect you might have missed out to create an injector on SNSModule.我怀疑您可能错过了在 SNSModule 上创建注入器的机会。 Add the following lines in the main-application-class:在 main-application-class 中添加以下几行:

Injector injector = Guice.createInjector(SNSModule);

The solution is quite tricky, the following worked for me on a sample project.解决方案非常棘手,以下在示例项目中对我有用。
lombok 1.8.4 Guice 4.2.2龙目岛 1.8.4 吉斯 4.2.2

You should create your own annotation and replace the @Named annotation with it see BindingAnnotations您应该创建自己的注释并用它替换 @Named 注释,请参阅BindingAnnotations
eg例如

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 {}

Then add a lombok.config file see here然后添加一个 lombok.config 文件见这里

in the file add the following line在文件中添加以下行

lombok.copyableAnnotations += org.company.PSSNS

in your 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;

Replace it in the Guice Module as well也可以在 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();
    }

}

When I tested that I needed to clean build from maven当我测试我需要从 maven 清理构建时

Look at the generated class and verify you can see it on the constructor.查看生成的类并验证您可以在构造函数中看到它。
This should allow Guice to inject all your constructor arguments.这应该允许 Guice 注入所有构造函数参数。

Lombok doesn't copy any annotations on the fields to the constructor parameters by default.默认情况下,Lombok 不会将字段上的任何注释复制到构造函数参数。 If you want to keep using @RequiredArgsConstructor(access = AccessLevel.PUBLIC, onConstructor = @__(@Inject)) , then add configurations for the same in your lombok.config file something like this:如果您想继续使用@RequiredArgsConstructor(access = AccessLevel.PUBLIC, onConstructor = @__(@Inject)) ,请在 lombok.config 文件中添加相同的配置,如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM