m-a.D
m-a.D

Reputation: 97

Springboot multiple @Configuration for the same Bean to add attributes

I'm fairly new to Springboot and I just stumbled on this code and was wondering if it's a good practice and what is going on behind the scene...

User.java

@Getter
@Setter
@NoArgsConstructor
public class User
{
    private String name;
    private String role;
    private String custom;
}

Config1.java :

@Configuration
public class Config1
{
    @Bean
    @Primary
    User createUser(){
        User user = new User();
        user.setName("John");
        user.setRole("dev");
        return user;
    }
}

Config2.java :

@Configuration
public class Config2
{
    @Bean
    User modifyUser(User user){
        user.setCustom("second configuration using the same bean ?");
        return user;
    }
}

End point :

@Autowired
private User user;

When I inspect the user variable, I notice that all 3 properties are filled. I'm assuming Spring uses Config1 to create the bean and then passes the reference to Config2. But I was wondering if this is a normal behavior, is there another way to do this ?

Context : In my case, Config1 is an external source that is included in the project and which I don't have any control. I want to set extra attributes from my application.yml file, hence the Config2. (I omited the @value in my example)

* EDIT with what I ended up doing *

Config2.java

@Configuration
public class Config2
{
    @Autowired
    private User user;

    @PostConstruct
    Private void init(){
        user.setCustom("second configuration using the same bean ?");
    }
}

Upvotes: 1

Views: 1973

Answers (1)

nicholas.hauschild
nicholas.hauschild

Reputation: 42834

I would argue that this is not good practice. There are basic spring lifecycle mechanisms at your disposal which can assist you with achieving your goal without giving that feeling of 'should-i-be-doing-it-this-way'?

Now, to answer your questions (or similar questions).

What is happening here?

Your assessment is correct. Config1 is creating a bean of type User, and that is being provided to Config2's modifyUser bean via the user parameter. This effectively creates two beans in the ApplicationContext, createUser and modifyUser that refer to the same bean (or different proxies of the same bean).

Is this bad?

Eh, I wouldn't say it is bad, but it certainly has a stink to it if you ask me. If your goal is to further configure a bean that was created elsewhere, I can think of better ways.

What are other options?

I would recommend one of the following options:

  1. Use a BeanPostProcessor -- This interface provides a method that can be used to customize a bean after it is instantiated postProcessAfterInitialization. The JavaDoc is fairly comprehensive, and should give enough information regarding how to use the method, so I won't repeat it here. Once you have created an implementation that does what you want, you can register this as a bean with the ApplicationContext (similar to what you have done already.
  2. Use the @PostConstruct annotation on an 'init' method in your Config2 class. Spring's ApplicationContext will recognize this, and invoke this method after it has constructed and initialized your Configuration class. The signature of such a method MUST return void and take no parameters, but your configuration class can have the User autowired in, to be used in said method. Outside of the return statement and the user parameter, you could pretty much use the modifyUser method as is.

Upvotes: 2

Related Questions