How to reference the default DataSource from another one?

45 Views Asked by At

I am writing a bean that wraps a DataSource to add some internal functionality to it. It seems that MyDataSource is trying to use itself in the constructor. My new class is shown below:

@Component
public class MyDataSource implements DataSource {

  public MyDataSource(DataSource wrapped) {
    // do something...
  }

}

When I try to run the application I get:

Error creating bean with name 'myDataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?

I don't control the creation of the normal DataSource at all, so it doesn't have a Qualifier or @Primary. I do control MyDataSource.

How do I tell my bean that it should use "the other DataSource" instead, and not itself during instantiation?

1

There are 1 best solutions below

2
Ken.Zhang On

This is common when your custom bean and the original bean are of the same interface type, like DataSource in your case. To solve this issue, you need to guide Spring on which bean to inject where, ensuring that your MyDataSource does not attempt to wrap itself, causing a circular reference.

There are several strategies to resolve this, but one common approach is to use @Qualifier annotation or defining your bean with a specific method and using @Primary. However, as you mentioned that you do not control the creation of the original DataSource and it does not have a @Qualifier or @Primary, we need to find another way.

A practical approach in your situation is to define an @Configuration class that explicitly configures your custom DataSource and uses it to wrap the existing DataSource bean.

  • Remove @Component from MyDataSource. This prevents Spring from trying to instantiate it automatically.
  • Create a Configuration Class. In this class, you will manually configure MyDataSource and inject the existing DataSource.
@Configuration
public class DataSourceConfig {

    @Bean
    public MyDataSource myDataSource(DataSource dataSource) {
        // Ensure that the dataSource bean injected here is the original DataSource
        // and not your MyDataSource. Spring should handle this automatically
        // since MyDataSource is now being created manually in this configuration.
        return new MyDataSource(dataSource);
    }
}

This configuration explicitly declares that your MyDataSource should wrap the DataSource bean that Spring automatically configures. Since MyDataSource is no longer annotated with @Component, Spring will not try to instantiate it automatically, thus avoiding the circular reference.