2
@Component
class MultiProvider {
    public Foo getFoo();
    public Bar getBar();
}

@Component
class FooConsumer {
    FooConsumer(Foo f);
}

Can I have MultiProvider.getFoo() autowired into the FooConsumer constructor..

  • without making Foo a bean itself (for example, because Spring should not destroy it, since that is MultiProviders responsibility)
  • and without introducing a dependency from FooConsumer to MultiProvider (or any other class)?
Bart van Heukelom
  • 43,244
  • 59
  • 186
  • 301

3 Answers3

0

Spring can only autowire declared beans, a possible workaround can be something like the following:

@Component
class FooConsumer {
    private final Foo foo;

    FooConsumer(MultiProvider multiProvider) {
        // MultiProvider will be autowired by spring - constructor injection
        this.foo = multiProvider.getFoo();
    }
}
Tom
  • 3,711
  • 2
  • 25
  • 31
  • Yes of course, but my purpose is to not have a dependency from FooConsumer on MultiProvider. I should clarify that – Bart van Heukelom Nov 10 '18 at 20:30
  • That is not possible as far as I know, you can only autowire beans – Tom Nov 10 '18 at 20:31
  • I don't know if its relevant, but you can specify `Foo` as a bean and add a `close()` method with your `destroy` logic so spring will destroy it correctly. Then you can maybe define it as a bean and autowire it - https://stackoverflow.com/a/44757112/4473822 – Tom Nov 10 '18 at 20:36
0

You can achieve this simply by annotating getFoo() method in MultiProvider by @Bean

@Component
class MultiProvider {
    @Bean(destroyMethodName="cleanup")      // HERE IS THE TRICK
    public Foo getFoo();
    public Bar getBar();
}

@Component
class FooConsumer {
    FooConsumer(Foo f);
}

if the problem comes from the point that spring can not properly destroy it you can include the logic inside cleanup method declared while annotating by @Bean

public class Foo {
    public void cleanup() {
        // destruction logic
    }
}    

Note that @component and @configurable are more or less the same with some subtle differences but in your case you can use @component if you don't want to change it. More Info

  • I've reworded my question a bit. I didn't want Spring to destroy Foo because that is MultiProviders responsibility. However, since destroy should be idempotent anyway (in my current opinion at least :P ) I was just being pedantic, and this is how I've solved it indeed (but without the custom `destroyMethodName`) – Bart van Heukelom Nov 14 '18 at 10:33
0

You can include them in your Configuration.

@Configuration
class MyConfig {
    @Bean
    public MultiProvider getMP() {
        return new MultiProvider() ;
   }
   @Bean
   public Foo getFoo() {
        return getMP(). getFoo();
   } 
}

Not sure if that violates your 'not a Bean itself' rule.

daniu
  • 14,137
  • 4
  • 32
  • 53