|

Spring series, part 5: @Component vs @Bean

In this post, I will look into the distinction between a component and a bean. Even though both of them refer to Spring managed beans, each serves a different purpose. @Component and its specializations (@Controller, @Service and @Repository) allow for auto-detection using classpath scanning. @Bean on the other hand can only be used to explicitly declare a single bean in a configuration class.


You might find interesting that components have been around for quite a long time, since Spring 2.5. Here is a brief overview of the component types and their purpose. As you will see in a short while, all component types are treated in the same way. The subtypes are mere markers, think code readability rather than features.

Component types and their purpose

Annotation Purpose
@Component A candidate for auto-detection via classpath scanning.
@Controller A web controller, popularized by Spring MVC.
@Repository Data manager / storage, ties to enterprise apps (DAO, DDD)
@Service Meant to provide business logic – a (stateless) facade.


I said there is no difference among the individual component types. Let’s prove it using a simple web app which exposes a single url returning a message in a JSON format. The front-end is, naturally, handled by a controller:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.zezutom.springseries0114.part04.model.Message; 

@Controller
@RequestMapping(″/web/message″)
public class WebController {
  @RequestMapping(method = RequestMethod.GET)
  public @ResponseBody Message message() {
    return new Message(″Controller″, ″An old good controller.″);
  }
}

However, any @Component would do, as shown on the following “controllers”. As long as it can be found on the classpath, it is good to use:

import org.springframework.stereotype.Component;
..
@Component // Not a controller?! Makes no difference
@RequestMapping(″/component/message″)
public class ComponentController {
  ..
}
import org.springframework.stereotype.Service;
..
@Service // Not a controller?! Makes no difference
@RequestMapping(″/service/message″)
public class ServiceController {
  ..
}

Now, a bean right? That’s a slightly different story. A @Bean-annotated class would not be found and could not be therefore used as a controller in the example above. Though, auto-wiring definitely applies here and provided the bean is defined in either an xml or a programmatic configuration it can be easily dependency-injected. Let’s promote code reusability and enhance our controllers with a dedicated message builder:

// Just a POJO
public class MessageBuilder {
  public Message getInstance(String title, String text) {
    return new Message(title, text);
  }
}
// Let's turn the POJO into a bean
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
..
@Configuration
public class AppConfig {
  @Bean
  public MessageBuilder messageBuilder() {
    return new MessageBuilder();
  }
}
// Finally, hook it up
..
@Autowired
private MessageBuilder messageBuilder;
..

The example is obviously fully covered by tests, feel free to download the source code and try it out.

Source Code

Previous: Part 4 – @Lazy on injection points 
Next: Part 6 – Spring 4 and generics-based injection matching

Similar Posts