what will happen if I override a bean definition i

2019-08-26 01:48发布

问题:

When developing with Spring Data Mongodb, I want to do some customization in my MongoDB configuraion. General, I will extends the AbstractMongoConfiguration, and implement the abstract methods. currently, the AbstractMongoConfiguration class has the following:

@Configuration
public abstract AbstractConfiguration extends MongoConfigurationSupport {
    public abstract MongoClient mongoClient();

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
          return new MongoTemplate(mongoDbFactor(), mappingMongoConverter());

    ....   
}

When extending this class, I want to customize the bean MongoTemplate, So I want to override the mongoTemplate method, does this work?

@Configuration
public MongoConfiguration extends AbstractConfiguration {
    public MongoClient mongoClient(){
        ....
    }

    @Override
    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
          MongoTemplate template = super.mongoTemplate();
          template.setWriteResultChecking(WriteResultChecking.EXCEPTION);
    }

    ....   
}

回答1:

The fact that you're using @Override in this case is not directly related to the concept of overriding a Spring Bean. Spring tracks beans by name, and it's possible to replace a bean with another one with the same name--this isn't used very often, but it's sometimes necessary to get around sticky situations. @Override is specifically a Java-inheritance bit.

In your case, your setup should work as you expect because when Spring instantiates your bean, it'll call MongoConfiguration#mongoTemplate(). If the definitions were in different classes, then they would both be producing beans named mongoTemplate, and the last one evaluated would win (there are tricks to controlling this explicitly, either using @Order or injecting the other configuration, but it's not ideal).

Note that in this specific case, you might prefer to use Spring Boot auto-configuration, in which case you wouldn't override the Java method. Instead, you could inject the MongoTemplate and just call the setter method on it, either by writing an ApplicationRunner or listening for ContextRefreshedEvent.



回答2:

Had an extremely similar issue recently.

There are 2 scenarios:

Case-1: Overriding without a qualifier

@Configuration
public MongoConfiguration extends AbstractConfiguration {
    public MongoClient mongoClient(){
        ....
    }

    @Override
    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
          MongoTemplate template = super.mongoTemplate();
          template.setWriteResultChecking(WriteResultChecking.EXCEPTION);
    }

    ....   
}

In this case, the bean will be registered by using your overridden definition and not your parent definition. Also, only 1 bean will be registered.

Case-2: Overriding with a qualifier

@Configuration
public MongoConfiguration extends AbstractConfiguration {
    public MongoClient mongoClient(){
        ....
    }

    @Override
    @Bean(name="myBean")
    public MongoTemplate mongoTemplate() throws Exception {
          MongoTemplate template = super.mongoTemplate();
          template.setWriteResultChecking(WriteResultChecking.EXCEPTION);
    }

    ....   
}

In this case, 2 beans(mongoTemplate and myBean) will be created. But, for the creation of both the beans, your overridden implementation will be used.