0

When using Spring Boot, a lot of beans are created implicitly by Spring Boot itself. For example, when I link the spring-boot-starter-data-redis dependency, the jedisConnectionFactory bean is created automatically under the hood.

What I'm looking for is the way to define my custom bean with a dependency on such an implicit bean, e.g. new MyService( jedisConnectionFactory ). The problem is that I don't have a variable or a method which would be resolved to that implicit bean.

For now I've come up with the following solution: create a separate BeanConfig class, autowire/inject ApplicationContext into it and then retrieve the required bean with ApplicationContext.getBean( Class<T> ) method call:

@Bean
public Transport eventTransport() {
    final JedisConnectionFactory jedisConnectionFactory = context.getBean( JedisConnectionFactory.class );
    return new RedisTransport( jedisConnectionFactory.getHostName(), jedisConnectionFactory.getPort() );
}

Is there any integrated way to get a reference to the beans defined internally? So that I could move this bean definition to MyApplication class without injecting the ApplicationContext instance.

2
  • Just add them as a method argument of the @Bean method. public Transport eventTransport(JedisConnectionFactory connectionFactory). Generally when you need to rely on the ApplicationContext (or BeanFactory) to retrieve beans you are, generally speaking, doing it wrong (if you aren't a framework/extension developer that is).
    – M. Deinum
    Commented Jun 6, 2017 at 11:44
  • @M.Deinum yes, I get it about using the context, that's why asking :) I think defining the method argument is right what I was looking for, so if you post it as an answer I'll accept it. Thanks!
    – scadge
    Commented Jun 6, 2017 at 12:44

2 Answers 2

2

First as a rule of thumb if you starting to resort to the ApplicationContext or BeanFactory to obtain beans you are, generally speaking, doing it wrong (at least when simply developing an application with Spring).

When using @Bean on a method, effectively making it a factory method for those beans, you can use 0 or more method arguments. (This is also explained in the reference guide). The arguments are resolved against the context and will have the beans injected (or fail starting if it cannot be found).

So in your case you can simply add JedisConnnectionFactory (or maybe the ConnectionFactory interface) as a method argument for your eventTransport method.

@Bean
public Transport eventTransport(final JedisConnectionFactory jedisConnectionFactory) {
    return new RedisTransport( jedisConnectionFactory.getHostName(), jedisConnectionFactory.getPort() );
}

This also allows Spring to resolve dependencies between beans instead of hoping the bean is already constructed and fully ready for use.

1
  • A special thanks for the documentation link - somehow I failed to find that on my own
    – scadge
    Commented Jun 6, 2017 at 15:10
0

If JedisConnectionFactory class is getting instantiated by spring then you can simply autowire this instance at the class level and use the same to create RedisTransport object.

@Autowired
private JedisConnectionFactory jedisConnectionFactory;

@Bean
public Transport eventTransport() {
    return new RedisTransport( jedisConnectionFactory.getHostName(), jedisConnectionFactory.getPort() );
}
1
  • 3
    Even better, just put it as a method argument, that way Spring is better able to determine the order of the beans.
    – M. Deinum
    Commented Jun 6, 2017 at 11:46

Not the answer you're looking for? Browse other questions tagged or ask your own question.