Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Supplier as a deferred bean creation [SPR-16973] #21511

Closed
spring-projects-issues opened this issue Jun 25, 2018 · 2 comments
Closed

Support for Supplier as a deferred bean creation [SPR-16973] #21511

spring-projects-issues opened this issue Jun 25, 2018 · 2 comments
Assignees
Labels
in: core status: declined type: enhancement

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Jun 25, 2018

Dave Syer opened SPR-16973 and commented

It's nice that Spring supports this kind of idiom for lazy initialization of Bar:

 

 @Bean
 public Foo foo(Provider<Bar> bar) {
    return new Foo(bar);
 }

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

 

It would be nice if it supported Supplier in place of Provider especially now that Java 8 is the baseline.


Affects: 5.0.7

Issue Links:

  • #21433 Introduce Stream support in PropertySources and PropertyValues
  • #21613 Programmatic ObjectProvider retrieval through BeanFactory API
@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 25, 2018

Dave Syer commented

It would be even nicer if there was a way to ask the BeanFactory directly for a Supplier because this could be used in functional bean registrations to make lazy assignments like the above. You can create the example above with bean registrations by making the configuration class implement BeanDefinitionRegistry (and removing the @Bean annotations):

 

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
		throws BeansException {
	BeanFactory context = (BeanFactory) registry;
	registry.registerBeanDefinition("runner",
			genericBeanDefinition(CommandLineRunner.class,
							() -> runner(context.getBean(Foo.class)))
					.getRawBeanDefinition());
	registry.registerBeanDefinition("foo",
			genericBeanDefinition(Foo.class,
							() -> foo(() ->  context.getBean(Bar.class)))
					.getRawBeanDefinition());
	registry.registerBeanDefinition("bar",
			genericBeanDefinition(Bar.class,
							() -> bar()).setLazyInit(true)
					.getRawBeanDefinition());
}

It works, but a) it's a bit ugly, and b) I would like to be able to use @Configuration classes to create bean definitions in the functional style, like the above, but I can't do it without using Provider in place of Supplier, and therefore I need JSR-330 on the classpath.

I could also achieve this goal if there was a way to use ObjectProvider in place of Supplier, but there isn't really because it's kind of an internal interface. And it's not functional of course. I ended up working round that by creating some convenience factories for ObjectProvider (they need a Method so they can inspect the generic type of the provider).

The BeanFactory perhaps could make this pattern more of a first class concept. Kind of off topic for the original issue here, but just showing some of what I have been thinking about.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jul 23, 2018

Dave Syer commented

Spring already has ObjectFactory which is a functional interface that supports the pattern above. It's better than Supplier because it has additional instance creation semantics (only once per singleton).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core status: declined type: enhancement
Projects
None yet
Development

No branches or pull requests

2 participants