I noticed AbstractEnvironment
has a reference to one of its parent interface ConfigurablePropertyResolver
(inherited through ConfigurableEnvironment
)
It also has a propertyResolver
which is of type ConfigurablePropertyResolver
.
This seems to enable delegating common interface methods to another PropertyResolver
method.
Attested, for example, in the following method, where the method getProperty
, common to both AbstractEnvironment
and ConfigurablePropertyResolver
, is delegated to propertyResolver
:
=Java
public String getProperty(String key) {
return this.propertyResolver.getProperty(key);
}
(This seems to be an example of the Proxy Pattern, but that is beside the point.)
I noticed the delegation only happens to methods defined in the PropertyResolver
and ConfigurablePropertyResolver
interfaces, which makes sense because only resolver-related methods should be decoupled into propertyResolver
and delegated. However, propertyResolver
having the type ConfigurablePropertyResolver
means anything of type ConfigurableEnvironment
can be assigned to it too and that any method defined in ConfigurableEnvironment
is also common to both AbstractEnvironment
and ConfigurablePropertyResolver
.
I wonder whether it's the original authors' intention for ConfigurableEnvironment
methods to be accessible, or even to be delegated to, through propertyResolver
?
I am asking that because I cannot find any instance of that in the code base. If that's not an intended purpose, is it perhaps better to set propertyResolver
to be of another type extended from ConfigurablePropertyResolver
as a Marker Interface?
Here is the class diagrams to illustrate the change:
Comment From: snicoll
I wonder whether it's the original authors' intention for ConfigurableEnvironment methods to be accessible, or even to be delegated to, through propertyResolver?
Yes. ConfigurableEnvironment
(or Environment
rather) is a special object type, at the same level as the ApplicationContext
or the BeanFactory
and being to configure things like placeholder settings must be accessible. Implementing the interface makes sure that we are consistent with the underlying feature and we don't duplicate contracts.