Why PostConstruct method does not work to keep bean init order when using in springboot?

Viewed 126

I have some config information in the database, when the springboot starts, it will load this information only one time. So I write the code like this:

@Configuration 
public class CommonConfig {
    private final DbConfigDao dbConfigDao;

    @Autowired
    public CommonConfig (DbConfigDao dbConfigDao) {
        this.dbConfigDao = dbConfigDao;
    }

    private int redisStoreDays; //omit get,set method
    
    @PostConstruct
    public void init() { 
        redisStoreDays = dbConfigDao.getValueByKey("redisStoreDays");
        //... continue to load the other config from db 
    }
}

In the other bean, I try to get the redisStoreDays value, it returns 0, but the real value is 1.

@Configuration 
public class  AutoConfiguration {

    @Conditional(RedisClusterConditional.class)
    @Bean(name = "redisDao", initMethod = "init")
    public RedisClusterDao getRedisClusterDao() {
        return new RedisClusterDaoImpl();
    }

    @Conditional(RedisSentryConditional.class)
    @Bean(name = "redisDao", initMethod = "init")
    public RedisSentryConditional getRedisSentryDao() {
        return new RedisSentryDaoImpl(); 
    }
}

public class RedisClusterDaoImpl implements RedisDao {  
    @Autowired
    private CommonConfig commonConfig; 
    private int storeDays = 7;  

    @Override
    public void init()  { 
        storeDays = 60 * 60 * 24 * commonConfig.getRedisStoreDays(); 
        //commonConfig.getRedisStoreDays is 0 but in fact is 1 
    }  
}

How to keep the bean init order? I try to add PostConstruct in my redis bean, but it still does not work.

I debug and find the commonConfig is not null, but commonConfig.getRedisStoreDays() returns 0.

After executing init method in RedisClusterDaoImpl, commonConfig.getRedisStoreDays() changes to 1.

I also try to add @AutoConfigureBefore(RedisClusterDao.class),but storeDays still gets 0 in RedisClusterDaoImpl class.

2 Answers

Use Spring's @DependsOn, i.e.:

@DependsOn("CommonConfig")
@Configuration
public class AutoConfiguration {
    ...
}

Why not

@Configuration 
public class CommonConfig {
    private final DbConfigDao dbConfigDao;

    @Autowired
    public CommonConfig (DbConfigDao dbConfigDao) {
        this.dbConfigDao = dbConfigDao;
        // why in PostConstruct? You have the bean right here, it should be initialized
        redisStoreDays = dbConfigDao.getValueByKey("redisStoreDays");
    }

    private int redisStoreDays; //omit get,set method
    
}

or just

public class RedisClusterDaoImpl implements RedisDao {  
    @Autowired
    private DbConfigDao commonConfig; 
    private int storeDays = 7;  

    @Override
    public void init()  { 
        storeDays = 60 * 60 * 24 * dbConfigDao.getValueByKey("redisStoreDays");
    }  
}

After all, this is the redis bean, I don't see why it shouldn't know the name of the config setting it needs.

Related