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
@ComponentA candidate for auto-detection via classpath scanning.
@ControllerA web controller, popularized by Spring MVC.
@RepositoryData manager / storage, ties to enterprise apps (DAO, DDD)
@ServiceMeant 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