Vinz243
Vinz243

Reputation: 9938

spring how to instantiate an @Autowired constructor without passing the parameter

Let's say I have this class

class Foo implements IFoo { Foo() {} }
class Fooz implements IFoo { Fooz() {}}

class Foobar implement IFoobar {
  @Autowired
  Foobar (Foo foo) {}
}

class Foobarz implement IFoobar {
  @Autowired
  Foobarz (Bar bar) {}
}

In asimple case I can do to solve my problem:

class Bar {
  @Autowired 
  Bar (IFoo foo) {
    this.foo = foo;
  }
}

However if I want to be able to select my IFoo and IFoobar instance according to my configuration file I need to do do:

@Configuration
class Configuration {
  @Bean
  foo () {
    return this.isZ() ? new Fooz() : new Foo ();
  }
  @Bean
  foobar () {
    return this.isZ() ? new Foobarz(/* ??????? */) : new Foobar (/* ??????? */);
  }
}

As you can see I can't instantiate my Foobar, since I need another bean. I know there is the ApplicationContext.getBean, but I can't be sure it will be indeed initialized in my Configuration class when foobar() gets called.

And I don't want to call this.foo() either, because that would create another reference of the object, and I'm not sure about the order of execution and initialization

Upvotes: 0

Views: 1287

Answers (1)

Nikolai  Shevchenko
Nikolai Shevchenko

Reputation: 7521

In your case following should do the trick

@Configuration
class Configuration {
  @Bean
  IFoo foo() {
    return this.isZ() ? new Fooz() : new Foo ();
  }
  @Bean
  IFoobar foobar(IFoo foo) { // IFoo bean declared above will be injected here by Spring
    return this.isZ() ? new Foobarz(foo) : new Foobar(foo);
  }
}

UPDATED

But more elegant way to do it is just to put @Service or @Component annotation on your class (@Bean declaration should be removed from configuration though) ...

package com.foobarpkg.maybeanotherpkg;

@Service 
class Foobar implement IFoobar {
  @Autowired
  Foobar (IFoo foo) { // not that interface should be used here instead of concrete class (Foo/Fooz)
  } 
}

... and let Spring know its package is located at

@Configuration
@ComponentScan(basePackages = {"com.foobarpkg"})
class Configuration { 
 @Bean
  IFoo foo() {
    return this.isZ() ? new Fooz() : new Foo ();
  }
  // foobar bean is no longer declared here
}

Upvotes: 1

Related Questions