Chapter 3. Bean Visibility

A nice JavaConfig feature is bean visibility. JavaConfig uses a method visibilty modifiers to determine if the bean resulted from that method can be accessed through by owning application context / bean factory or not.

Consider the following configuration:

@Configuration
public abstract class VisibilityConfiguration {

  @Bean
  public Bean publicBean() {
     Bean bean = new Bean();
     bean.setDependency(hiddenBean());
     return bean;
  }
  
  @Bean
  protected HiddenBean hiddenBean() {
     return new Bean("protected bean");
  }

  @Bean
  private HiddenBean secretBean() {
     Bean bean = new Bean("private bean");
     // hidden beans can access beans defined in the 'owning' context
     bean.setDependency(outsideBean());
  }

  @ExternalBean
  public abstract Bean outsideBean()
}

used along side the following XML configuration (for more information on mixing configuration strategies see this chapter) :

<beans>
 <!-- the configuration above -->
 <bean class="my.java.config.VisibilityConfiguration"/>

 <!-- Java Configuration post processor -->
 <bean class="org.springframework.config.java.process.ConfigurationPostProcessor"/>

 <bean id="mainBean" class="my.company.Bean">
    <!-- this will work -->
    <property name="dependency" ref="publicBean"/>
    <!-- this will *not* work -->
    <property name="anotherDependency" ref="hiddenBean"/>
 </bean>
</beans>

One JavaConfig will encounter the configuration above, it will create 3 beans : publicBean, hiddenBean and secretBean. All of them can see each other however, beans created in the 'owning' application context (the application context that bootstraps JavaConfig) will see only publicBean. Both hiddenBean and secretBean can be accessed only by beans created inside VisibilityConfiguration.

Any @Bean annotated method, which is not public (i.e. with protected, private and default visibility), will create a 'hidden' bean.

In the example above, mainBean has been configured with both publicBean and hiddenBean. However, since the latter is (as the name imply) hidden, at runtime Spring will throw:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'hiddenBean' is defined
 ...

To provide the visibility functionality, JavaConfig takes advantage of the application context hierarchy provided by the Spring container, placing all hidden beans for a particular configuration class, inside a child application context Thus, the hidden beans can access beans defined in the parent (or owning) context but not the other way around.