The most benefit of using a framework like Spring is auto-configuration. By only introducing the library or the module to the classpath, Spring could automatically scan it and create the necessary object and @Autowrired
it.
@Component
is an annotation that annotates a class. It tells Spring to use this class to create a bean if there is somewhere else depend on this class. The creation of the class is totally controlled by Spring. And only one bean created per class.
@Component
class UserService {
public void updateUser(User user) {
…
}
}
@Controller
class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
}
In this example, Spring will recognize the appearance of the UserSerivc
e class because it was marked with @Component
annotation. So when it tries to initiate the UserController
object, it knows that it needs a UserService
to put to UserController
constructor. And the creation of the UserService
will be controlled totally by Spring. It is a pretty declarative way to define dependency.
With @Component
our life is so good. So why do we even need something like @Bean
annotation? When should we use it? First, @Bean
is an annotation that used for annotating the function (not a class) that will return an object of a class that will be registered as a bean object by Spring.
You could use it in case you are using a third-party library when you don’t have access to the source code of the library. So you can’t just put @Component
annotation of the class that you to create a bean.
You can combine with the @Configuration
annotated the class that contains the method return the beans or otherwise Spring won’t catch and register it as a bean for your dependency resolution.
Let’s consider this example.
class UserService {
private final PasswordEncoder encoder;
@Autowired
public UserService(PasswordEncoder encoder) {
this.encoder = encoder;
}
public String createUser(UserCreateReq req) {
UserEntity user = UserEntity.builder()
.setPassword(this.encoder.encode(req.getPassword()))
…
.build();
repo.save(user);
}
}
@Configuration
class PasswordEncoderConfiguration {
@Bean
public PasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
In this example, I couldn’t change the code base of the bcrypt library so to create the encoder object. I have to use a @Configuration
class to create the bean that I need in a method inside that @Configuration
class. In this way, we could create as many as you want bean objects. And you have to explicitly configure those bean by yourself when the conflict happens. One way to resolve that conflict is by using the @Qualifier
annotation in the constructor of the dependent class.
That's all. Happy coding.
Top comments (0)