Thursday, July 31, 2008

Stupid Scala Trick: Injecting Methods With Spring

I'm not sure why I came up with this idea, but it occurred to me that since functions are first class objects in Scala then I should be able to inject them as dependencies using the Spring framework. So I decided to give it a try (using constructor injection to make life simple).

First, I need a class that will have a method injected -


class User(val f: String => String) {

def b() = {f("hello")}

}

So, this class will have a method named f (which takes a String and returns a String) injected into it. It also has a method called b, which will use f.

Next up, a function that will be injected.

object func1 extends Function1[String, String] {
def apply(s: String): String = {s.toUpperCase()}
}

This is essentially the same as

def func1(s: String): String = {s.toUpperCase()}

Now, the Spring bean definition xml (which I'll save in a file called app.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">


<bean id="user" class="User">
<constructor-arg>
<bean class="func1$"/>
</constructor-arg>
</bean>
</beans>


Finally, a small application to fire up spring and test that injection worked


import org.springframework.context.support._

object SpringTest {

def main(args: Array[String]) = {

val context = new ClassPathXmlApplicationContext(Array[String]("app.xml"));
val user = context.getBean("user").asInstanceOf[User]
println(user.b())
println(user.f("world"))
}
}



And here's the output (minus some log4j warnings)


HELLO
WORLD

No comments: