Spring 3 part 2: Auto wiring

This is the 2nd part of the Spring 3 Series.

In the first part of this series, I discussed how to create maven Spring 3 project.The objective of the second part is to discuss the Spring 3 auto-wiring. Fist look into the Spring 2.5 auto-wiring which is based on the byName, byType, constructor and autodetect.

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

<!-- context:annotation-config/-->

<bean id="parent" class="au.com.blogspot.ojitha.spring3tut1.Parent" autowire="byType"></bean>
<bean id="child" class="au.com.blogspot.ojitha.spring3tut1.Child"></bean>
</beans>

As shown in the above configuration, beans are auto-wired.

Here the  parent and child relationship.

image

package au.com.blogspot.ojitha.spring3tut1;


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

public class Parent {
private Child child;


public void setChild(Child child){
this.child = child;
}

public Child getChild(){
return this.child;
}

/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
Parent parent = (Parent) ctx.getBean("parent");
parent.getChild().sayHello();

}

}

Here the Child class

package au.com.blogspot.ojitha.spring3tut1;

public class Child {
public void sayHello(){
System.out.println("Hello");
}

}

Using @Autowired annotation, beans can be wired without spring-config.xml file. The spring-config.xml version is as follows

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

<context:annotation-config/>

<bean id="parent" class="au.com.blogspot.ojitha.spring3tut1.Parent"></bean>
<bean id="child" class="au.com.blogspot.ojitha.spring3tut1.Child"></bean>
</beans>

The most important tag is  <context:annotation-config/> which auto wire the beans. In addition to that, @Autowired should be included in the Parent class as follows

public class Parent {
private Child child;

@Autowired
public void setChild(Child child){
this.child = child;
}

This tag is applicable when there is exactly one bean that’s applicable for wiring into the @Autowired property(even private) or parameter. If there are more applicable beans or no bean this tag is in the problem. The @Autowired (required=false) make the auto-wiring optional.

Let’s think about the situation as shown in the following class diagram,

image

  As shown in the above diagram, Child is abstract class, and the Parent class can either use GrandChild or MyChild as stated in the concept of polymorphism. The relevant configuration is

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

<context:annotation-config/>

<bean id="parent" class="au.com.blogspot.ojitha.spring3tut1.Parent"></bean>
<bean id="child" class="au.com.blogspot.ojitha.spring3tut1.MyChild"></bean>
<bean id="grandChild" class="au.com.blogspot.ojitha.spring3tut1.GrandChild"></bean>
</beans>

The Child class is abstract and it has only one sayHello() abstract method

package au.com.blogspot.ojitha.spring3tut1;

public abstract class Child {
abstract public void sayHello();
}

How to switch MyChild or GrandChild in Parent class ? How to resolve this ambiguity ?

public class Parent {
@Autowired
@Qualifier("grandChild")
private Child child;

The class MyChild will be selected by the spring container because the @Qualifier parameter specifies the “grandChild” which is already declared in the spring-config.xml file. if you need MyChild, then the @Qualifier(“child”).

The alternative way (I think best way) is to create custom Qualifier as shown the following code

package au.com.blogspot.ojitha.spring3tut1;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.annotation.Qualifier;

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface GrandChildQualifier {

}

This qualifier can be used to qualify the GrandChild class

package au.com.blogspot.ojitha.spring3tut1;

@GrandChildQualifier
public class GrandChild extends Child {
@Override
public void sayHello(){
System.out.println("I am grand child...");
}
}

In the Parent class, refer to the custom qualifier

public class Parent {
@Autowired
@GrandChildQualifier
private Child child;

In this part, I discussed the Spring way of auto wiring. In the next part I am looking into the standard wiring.

Comments

Popular posts from this blog

How To: GitHub projects in Spring Tool Suite

Spring 3 Part 7: Spring with Databases

Parse the namespace based XML using Python