Tuesday, 25 April 2017

Spring: Method Injection

In my previous post, I explained singleton and prototype bean scopes. In a typical application, one bean is dependent of more than one bean. If one singleton bean uses another singleton bean (or) one non-singleton bean uses another non-singletong bean is absolutly fine. But the problem arises, when the bean scopes are different.

For example,
If singleton bean 'A' uses the non-singleton bean 'B'. Whenever the application request for the instance of 'A', then Spring IOC returns the same instance, since 'A' is of scope singleton. The container cannot provide bean A with a new instance of bean B every time one is needed.

Lookup method injection
Lookup method injection is a technique provided by the Spring IOC container to override methods on container managed beans, to return the lookup result for another named bean in the container.

Let’s see an example without method injection first.

A.java
package com.sample.pojo;

public class A {
 public A() {
  System.out.println("Constructor A is created");
 }

 private B dependency;

 public B getDependency() {
  return dependency;
 }

 public void setDependency(B dependency) {
  this.dependency = dependency;
 }

}

B.java
package com.sample.pojo;

public class B {
 public B(){
  System.out.println("Constructor B is created");
 }
}

myConfiguration.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.xsd">

 <bean id="a" name="a" class="com.sample.pojo.A">
  <property name="dependency" ref="b" />
 </bean>

 <bean id="b" name="b" class="com.sample.pojo.B" scope="prototype" />

</beans>

HelloWorld.java
package com.sample.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.sample.pojo.A;

public class HelloWorld {
 public static void main(String args[]) {
  ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "myConfiguration.xml" });

  A obj1 = context.getBean("a", A.class);
  A obj2 = context.getBean("a", A.class);

  ((ClassPathXmlApplicationContext) context).close();
 }
}

Output
Constructor A is created
Constructor B is created

Notify the output, the constructors are called once. Since my bean ‘b’ is defined with prototype scope, I am expecting it to be return new instance on every bean request of type b.

Now let’s see how to solve this problem using method injection.

Update class A like below.

A.java
package com.sample.pojo;

public abstract class A {
 public A() {
  System.out.println("Constructor A is created");
 }

 public abstract B getDependency();

}


Spring Framework generate a dynamic subclass of ‘A’ that will override the getDependency method to provide a new instance of ‘B’ every time it is requested for.

You can now define the name of lookup-method name in the Myclass bean definition as this:

myConfiguration.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.xsd">

 <bean id="a" name="a" class="com.sample.pojo.A">
  <lookup-method name="getDependency" bean="b" />
 </bean>

 <bean id="b" name="b" class="com.sample.pojo.B" scope="prototype" />

</beans>

HelloWorld.java
package com.sample.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.sample.pojo.A;

public class HelloWorld {
 public static void main(String args[]) {
  ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "myConfiguration.xml" });

  A obj1 = context.getBean("a", A.class);
  A obj2 = context.getBean("a", A.class);
  
  obj1.getDependency();
  obj2.getDependency();

  ((ClassPathXmlApplicationContext) context).close();
 }
}

Output
Constructor A is created
Constructor B is created
Constructor B is created



Previous                                                 Next                                                 Home

No comments:

Post a Comment