简体   繁体   中英

guice : No implementation for interface was bound

Is it ok to bind in interface with guice? the error is No implementation for com.tobris.apps.base.service.user.UserService was bound.

UserService is an interface.


  @Inject
  public SyncContactService(
      PartnerRepository partnerRepo,
      CompanyRepository companyRepo,
      CityRepository cityRepo,
      CountryRepository countryRepo,
      AddressRepository addressRepo,
      SyncContactRepository syncContactRepo,
      EmailAddressRepository emailAddressRepo,
      UserService userService,
      FunctionRepository functionRepo) {
    this.partnerRepo = partnerRepo;
    this.companyRepo = companyRepo;
    this.cityRepo = cityRepo;
    this.countryRepo = countryRepo;
    this.addressRepo = addressRepo;
    this.syncContactRepo = syncContactRepo;
    this.emailAddressRepo = emailAddressRepo;
    this.userService = userService;
    this.functionRepo = functionRepo;
  }

this is the binding code :

    // bind all the web service resources
    for (Class<?> type :
        MetaScanner.findSubTypesOf(Object.class)
            .having(Path.class)
            .having(Provider.class)
            .any()
            .find()) {
      bind(type);
    }

Guice works with explicit bindings, not implicit ones.

When you bind() a type, you actually bind that type and not any of its interfaces or superclasses. That means that for a class such as ArrayList , which implements several interfaces and has several super classes, only ArrayList will be binded, not List , not AbstractList to take a few.

Therefore, the best approach is to find all subtypes of the type you want to bind, and make sure there's only one appropriate implementation.

In terms of code, what you should do is the following:

ScopedBindingBuilder bindScannedImplementation(Class<?> baseType) {
  var subtypes = MetaScanner.findSubTypesOf(baseType)
            .having(Path.class)
            .having(Provider.class)
            .any()
            .find();
  var implementations = subtypes.stream()
            .filter(this::isConcreteClass)
            .toList();
  if (implementations.size() != 1) {
    throw new RuntimeException("Too many or too few implementations for " + baseType.getName());
  }
  var implementation = implementations.get(0);
  return bind(baseType.class).to(implementation);
}
private boolean isConcreteClass(Class<?> c) {
  if (c.isInterface()) return false;
  if ((c.getModifiers() & Modifier.ABSTRACT) != 0) return false;
  return true;
}

Then, you have to explicitly bind the types you want:

bindScannedImplementation(UserService.class).in(Singleton.class);

这可能会有所帮助,我发现在接口声明中添加@ImplementedBy()注释更实用。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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