JiKra
JiKra

Reputation: 1790

How does Spring configuration class get instance of objects expected by its methods?

There are several features in Spring that are sort of black box for me. In this case, I'm playing with websockets and there is @Configuration class implementing or extending something with overrided methods that expects instantiated objects as parameters.

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic");
        registry.setApplicationDestinationPrefixes("/app");
    }
}

Method configureMessageBroker expects instance of MessageBrokerRegistry class, but there isn't any bean configuration in the whole project.

My question is, where does Spring get an instance of those classes?

Upvotes: 2

Views: 1248

Answers (2)

Shubham Kadlag
Shubham Kadlag

Reputation: 2308

This is not only for @EnableWebSocketMessageBroker but for any other spring configuration. What you need to understand is when you run the project, spring creates the required objects, in this case MessageBrokerRegistry, inject it, then pass it to configureMessageBroker and call the method. This is the reason you add @Configuration annotation to a class. This annotation tells spring to initialize the related environment during spring initialization.

Another example:

@Configuration
@EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter {
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

}

Now here we need DefaultServletHandlerConfigurer and it is created and managed completely by spring.The configureDefaultServletHandling() method is overridden and we enable default servlet handler. This will let other http request such as .css, .js slip through the usual DispatcherServlet and let the container process them. So now we can serve the static files css and javascript from our WebApp folder.

In short, @Configuration tells spring to set up the environment, so all the method in a class annotated with @Configuration are for initialization and are only and only for spring to manage.

As pointed out by Esther Álvarez Feijoo, you can understand it better by debugging.

Upvotes: 7

@Configuration annotates that class also as a @Component (See the code of @Configuration, it has that annotation). This way, an instance of your WebSocketConfig is available in the IoC container. The method "configureMessageBroker" is not magically invoked just because of that, and the argument "MessageBrokerRegistry registry" is not injected. It's just a regular method, that anybody with the class instance can invoke, passing the suitable argument

When running your app, in some step of spring initialization, spring will need to configure the web socket utilities, and will look for a implementation of "AbstractWebSocketMessageBrokerConfigurer", or some or its interfaces. It'll find your class instance, and use it for that configuration, passing the necessary parameters to the methods, because Spring already have them.

You can see this behaviour much better with the debugger. Put a break point in your method, and see the call stack. You can do reverse engineering and see how your method is invoked.

Upvotes: 2

Related Questions