LIvanov
LIvanov

Reputation: 1336

Provide single @Bean that can be used to inject in multiple interfaces

Consider the following piece of code

public interface Iface1 { }
public interface Iface2 { }

public class A implements Iface1, Iface2 {

}

@Configuration
public class AutoConfig {

  @Bean
  Iface1 provideIface1Impl() {
      return new A();  // instance no 1234
  }

  @Bean
  @ConditionalOnBean(A.class)
  @Autowired
  Iface2 provideIface2Impl(A aImpl) {
    return aImpl;
  }
}

I would like the second @Bean method to be autowired with the instance from the first one (1234) and I'd like the second @Bean method to return the same instance, so that I can use the same instance for clients of Iface1 and Iface2.

Current problem is that spring doesn't run the second @Bean because there is no @Bean of type A.class - the created bean is considered as Iface1 even though it is of type A.

Upvotes: 0

Views: 96

Answers (3)

Yoory N.
Yoory N.

Reputation: 5464

Additionally to what others have answered, I'd like to cover that part of the question that touches bean's dependencies. To inject a dependency to a @Bean-annotated method, there are two ways:

Examples of both:

@Configuration
public class AppConfig {

    @Bean
    public Foo foo() {
        return new Foo();
    }

    @Bean
    public Bar bar() {
        return new Bar(foo());
    }

    @Bean
    public Baz baz(Foo foo) {
        return new Baz(foo);
    }
}

So your provideIface2Impl could look like this:

@Bean
Iface2 provideIface2Impl(A aImpl) {
    return aImpl;
}

// or...

@Bean
Iface2 provideIface2Impl() {
    return (Iface2)provideIface1Impl();
}

But don't use it this way, it will lead to subtle bugs like double-proxying or "No unique bean of type" error, etc. Prefer what Gorazd suggested.

Upvotes: 0

Gorazd Rebolj
Gorazd Rebolj

Reputation: 825

Just define bean A. When injecting IFace1 and Iface2 they will automatically resolve to A (if A is the only implementation of course).

@Bean
public A a() {
    return new A();
}

Upvotes: 2

Mykola Yashchenko
Mykola Yashchenko

Reputation: 5371

I think you should try to define only one @Bean. It will create a singleton:

@Bean
public A a() {
      return new A();
}

Then just use the name of this bean in @Qualifier annotation:

@Autowired
@Qualifier("a")
private Iface1 iface1;

@Autowired
@Qualifier("a")
private Iface2 iface2;

Upvotes: 0

Related Questions