Using Java Lambda Function Inside Spring XML

Say I have this class:

public class FooToBarTransformer { public Bar transform(Foo foo) { // do some cool stuff } } 

And I want to use it as Function in some other class:

 public class Thing { public Thing(Function<Foo, Bar> f) { this.converter = f; } } 

Now, if I create Thing through Java, I would do it using Java8 Lambdas as follows:

 FooToBarTransformer transformer = new FooToBarTransformer(); new Thing((foo) -> transformer.transform(foo)); // or new Thing(transformer::transform); 

My problem is that I need to create Thing though spring .

 <bean id="fooToBarTransformer" class="com.mypackage.FooToBarTransformer"/> <bean id="theThing" class="com.mypackage.Thing"> <constructor-arg index="0" ????????? /> </bean> 

Now there are several possible workarounds that I decided to make easier:

  • If FooToBarTransformer implemented by Function , then it will just be ref="fooToBarTransformer"
  • I could create another interface that FooToBarTransformer implements and modifies Thing to take an instance of this interface instead of Function . For the purposes of this question, none of them is a parameter.

Based on some other methods that I saw when executing executions in spring xml, I tried value="#{(foo) -> fooToBarTransformer.transform(foo)}" and value="#{fooToBarTransformer::transform}" , but spring rustled on this.

The best option I came with is to provide a translation function in code:

 public Function<Foo, Bar> toFunction() { return transformer::transform; } 

and refer to it in spring at value="#{fooToBarTransformer.toFunction()}" , but that seems pretty hokey.

Is there a better way to do this?

+9
source share
2 answers

I think you need to switch to Java Config ( http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-java ) At the same time, if you cannot switch , you can pull it by combining methods. In the XML configuration file, add:

 <bean class="com.myapp.config.FooBarConfiguration"/> 

Then you create the class com.myapp.config.FooBarConfiguration as follows:

 @Configuration public class FooBarConfiguration { @Bean public FooToBarTransformer fooTransformer() { return new FooToBarTransformer(); } @Bean public Thing theThing(FooToBarTransformer fooTransformer) { return new Thing(fooTransformer::transform); } } 

Just make sure that ConfigurationClassPostProcessor is a registered post processor in your Spring context, either by having:

<context:annotation-config>

or

<context:component-scan>

Or manually adding the mail processor as a bean:

<bean class="org.springframework.context.annotation.ConfigurationClassPostProcessor"/>

This should work from Spring 3.0 and up according to http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/annotation/ConfigurationClassPostProcessor.html . Not sure which version you are using.

+2
source

Try using the factory template. See Org.springframework.beans.factory.FactoryBean. Spring also has an expression language.

0
source

Source: https://habr.com/ru/post/989838/


All Articles