A short story of the Java-based container configuration in the Spring Framework

A few weeks ago my workmate asked me a question: “How does the Spring Framework handle a self-invocation on a creation of beans?” He was thinking about a situation like this one:

@Configuration
class MyConfig {

    @Bean
    ABean aBean() {
        return new ABean(this.bBean())
    }
    
    @Bean
    BBean bBean() {
        return new BBean()
    }
}

In this case we see that during the creation of the aBean we invoke a method, which creates the bBean.

From my past experience I know that an invocation of methods on the same bean (self-invocation) will bypass the AOP mechanism. I know that with the AspectJ configured in the Spring framework, self-invocations will work. However, they have implemented it only with the CGLib for @Configuration annotation. How did they achieve this? I had always thought that the Spring Framework uses “normal” aspect based implementation of the annotations @Bean and @Configuration.

When I realized this situation was true I thought that I needed to immediately start a mission to research what the magic forces are making the @Configuration work with self-invocations.

I discovered that there is a wizard named the ConfigurationClassEnhancer. This class is responsible for the whole magic. It adds the BeanMethodInterceptor, which makes self-invocation possible. In this case they have chosen to invoke the invokeSuper method in interceptor rather than delegating logic to a aggregated proxy object. This is the reason why the self-invocation on creation of beans work.

During the investigation of the @Configuration incident I have found out that the CGLIB tutorial is very interesting reading.