Equivalent to BeanFactoryAware, and BenNameAware?

22 views
Skip to first unread message

Jochen Wiedmann

unread,
Nov 21, 2021, 5:11:43 AM11/21/21
to google-guice

Hi,

I am investigating, what the efforts would be to migrate an existing application from
Spring Beans to Guice. One of the problems, that I am facing is this:

In Spring Beans, there are two special interfaces, called BeanFactoryAware, and BeanNameAware.

The first one is used to a) semi-inject the BeanFactory (the Spring Beans equivalent of the Injector), but also to b) provide a point, where the Bean can initialize itself, because it can now assume, that the injected values are present.

The second one injects the value of the @Named annotation.

Now, I could replace these, but it would take considerable efforts, and require a significant amount of testing. So, the question:

Is there any chance to have something similar with Guice?

Thanks,

Jochen

Piotr Morgwai Kotarbinski

unread,
Nov 21, 2021, 11:17:34 PM11/21/21
to google-guice
Hi,
I'm *almost* sure that there's no equivalent in Guice as these mechanisms promote bad design: objects should rather be initialized in their constructors and regarding `BeanNameAware` even its javadoc says "Note that it is not usually recommended that an object depends on its bean name, as this represents a potentially brittle dependence on external configuration, as well as a possibly unnecessary dependence on a Spring API".

For name injection, you could create a simple custom `Provider` for each binding, but as I understand this exactly what you are trying to avoid:
```
bind(SomeBean.class).annotatedWith(Names.named("beanName")).toProvider(() -> {
    final var bean = new SomeBeanImpl();  // or whatever else way to create an instance
    bean.setBeanName("beanName");
    return bean;
});
```
Other than the above, you could try writing Guice extension using its SPI (Service Provider Interface) and check if the class of the implementation implements your interface and if so, retrieve `@Named` value from the key and call your  `setBeanName(name)`. Have a look at https://github.com/google/guice/wiki/ExtendingGuice and other subsections of `Extensions` section.

For `BeanFactoryAware` issue a), as you probably know, you can always inject `Injector` itself (just add as a constructor param or an injectable field: `@Inject Injector injector`), but this is also discouraged in most cases: dependencies of your objects should rather be explicitly enumerated, ideally as constructor params.

For providing initialization point, again: this should ideally be done in constructors. Other than that you can try these ways:
- manually create simple custom `Provider` that calls `initialize()` for each binding of a class that needs to be initialized `  post constructor (again, as I understand that's what you are trying to avoid).
- similarly like for name injection, you could try using SPI and check for yet another interface with some `initialize()` method.
- set all dependencies (including `Injector` if needed) of your bean with a single method (like `@Inject void setDependencies(Dep1 dep1, Dep2 dep2 /* and so on */)`) and perform initialization there.

Hope this helps in some way :)

Cheers!
Reply all
Reply to author
Forward
0 new messages