Spring 5 lookup method dependency injection example
In the Spring framework, most of the time we do the setter-based or constructor-based dependency injection but in this tutorial, we will learn about one more type of dependency injection i.e. method or lookup method injection. Lookup method injection is the ability of the container to override methods on container managed beans, to return the lookup result for another named bean in the container. To do this Spring provide <looup-method />
child element of <bean />
element.
Lookup method: If a method not having any implementation or if method required any dependencies, we can consider those methods as a lookup method.
The Spring framework implements method injection by using bytecode generation from the CGLIB
library to generate dynamically a subclass that overrides the method. The lookup typically involves a prototype bean.
Consider the below snippet of the interface, abstract class, and concrete class.
public interface Employee {
public void hike();
}
In the above interface, we can consider the hike()
as a lookup method. For the abstract class, it may have the abstract method or it may not have.
abstract public class Movies {
abstract public void showTime();
}
Here we can consider showTime()
method as lookup method to provide its implementation. And if you have a concrete class with a fully implemented method.
public class Adventure {
public void bikeAdventure() {
// implementation
}
}
If you want to override the bikeAdventure()
method implementation, then we can consider it as a lookup method.
Note: In lookup method injection, we are basically overriding the method and provide its implementation.
Let’s check the complete example of all possible cases.
Technologies Used
Check the list of all the technologies used in this example.
- Spring-5.0.2.RELEASE
- JDK 8
- Eclipse IDE and
- CGLIB library
Spring Beans
Create the four different bean classes for method injection. In my example, I have Engine
bean class for injecting value to lookup method using setter-based di.
package org.websparrow.beans;
public class Engine {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
And a Car
interface has Engine
type lookup method.
package org.websparrow.beans;
public interface Car {
public Engine myCarEngine();
}
An abstract class Bus
having an abstract Engine
type lookup method.
package org.websparrow.beans;
abstract public class Bus {
abstract public Engine myBusEngine();
}
And finally, a concrete class Truck
having a full implemented Engine
type lookup method.
package org.websparrow.beans;
public class Truck {
public Engine myTruckEngine() {
Engine e = new Engine();
e.setName("ASHOKA Truck Engine");
return e;
}
}
Spring Beans Configuration
In the configuration file, use the <looup-method />
child element of <bean />
element. To provide the implementation of a method or override the method, pass the method name to the name attribute and bean reference id.
<?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.xsd">
<!-- for car interface provide look-up method di -->
<bean id="car" class="org.websparrow.beans.Car">
<lookup-method name="myCarEngine" bean="e" />
</bean>
<bean id="e" class="org.websparrow.beans.Engine">
<property name="name" value="BMW Car Engine" />
</bean>
<!-- for bus abstract class provide look-up method di -->
<bean id="bus" class="org.websparrow.beans.Bus">
<lookup-method name="myBusEngine" bean="e1" />
</bean>
<bean id="e1" class="org.websparrow.beans.Engine">
<property name="name" value="Volvo Bus Engine" />
</bean>
<!-- for truck concrete class provide look-up method di -->
<bean id="truck" class="org.websparrow.beans.Truck">
<lookup-method name="myTruckEngine" bean="e2" />
</bean>
<bean id="e2" class="org.websparrow.beans.Engine">
<property name="name" value="TATA Truck Engine" />
</bean>
</beans>
Run it
To test it load the configuration into the IoC container and run it.
package org.websparrow.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.websparrow.beans.Bus;
import org.websparrow.beans.Car;
import org.websparrow.beans.Truck;
public class Test {
public static void main(String[] args) {
ApplicationContext ap = new ClassPathXmlApplicationContext("spring.xml");
System.out.println("............CAR...........");
Car car = (Car) ap.getBean("car");
System.out.println(car.myCarEngine().getName());
System.out.println("............BUS...........");
Bus bus = (Bus) ap.getBean("bus");
System.out.println(bus.myBusEngine().getName());
System.out.println("............TRUCK...........");
Truck truck = (Truck) ap.getBean("truck");
System.out.println(truck.myTruckEngine().getName());
}
}
You will get the following result on your console log.
............CAR...........
BMW Car Engine
............BUS...........
Volvo Bus Engine
............TRUCK...........
TATA Truck Engine
How does it work?
In most of the scenario, we do the setter or constructor based dependency injection for Collection, Arrays, String, etc. and also create the implementation. So by using Spring XML file, we create the object of bean classes and do dependency injection. If you want to provide implementation is it possible to write code in the XML file, it is not possible
, we can create bean class and into bean class, we can do dependency injection.
To provide lookup method injection Spring will provide the implementation classes. At runtime, Spring generates proxy classes extended from the original class using CGLIB
library and by generating the proxy class, it will override the lookup method. We can see the implementation class by using getClass().getCanonicalName()
method. To test it, replace the NewTest
class with the below code.
package org.websparrow.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.websparrow.beans.Bus;
import org.websparrow.beans.Car;
import org.websparrow.beans.Truck;
public class NewTest {
public static void main(String[] args) {
ApplicationContext ap = new ClassPathXmlApplicationContext("spring.xml");
System.out.println("............CAR...........");
Car car = (Car) ap.getBean("car");
System.out.println(car.getClass().getCanonicalName());
System.out.println(car.myCarEngine().getName());
System.out.println("............BUS...........");
Bus bus = (Bus) ap.getBean("bus");
System.out.println(bus.getClass().getCanonicalName());
System.out.println(bus.myBusEngine().getName());
System.out.println("............TRUCK...........");
Truck truck = (Truck) ap.getBean("truck");
System.out.println(truck.getClass().getCanonicalName());
System.out.println(truck.myTruckEngine().getName());
}
}
Download Source Code: spring5-lookup-method-dependency-injection-example