Spring 3 part 3: Standard wiring

This is the 3rd part of the Spring 3 Series.

In the part 2 of this series explained the Spring way of wiring. The part 2 examples are continued in this blog.mThis part is dedicated to standard wiring that is proposed by the Java Community Process. Spring 3 implements the JSR-330 that is @Inject annotation.

The @Inject is lot common to the @Autowire but no “required” attribute.

import javax.inject.Inject;
import javax.inject.Named;

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

public class Parent {
@Inject
@Named("grandChild")
private Child child;

The Parent class’s child property is annotated with @Inject and @Named. Here @Named is similar to @Qualifier, for instance grandChild is declared as a Spring bean in the spring-config.xml file which is referenced in the @Named annotation. It is also possible to create custom qualifier as an alternative way.

Here the custom qualifier

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 javax.inject.Qualifier;
//import org.springframework.beans.factory.annotation.Qualifier;

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

}

and the Parent class refer to this custom qualifier as follows

import javax.inject.Inject;

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

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

It is important to not that javax.inject package is JCP standard which is available via maven repository by adding the following dependency,

    <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>

There is a way to avoid spring bean declaration in the spring-config.xml file: the magic is @Component. For example, in the spring-config.xml file “component-scan” is enabled and commented out all the bean declarations;

<?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:component-scan base-package="au.com.blogspot.ojitha.spring3tut1"/>

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

The Parent bean can be declared as component and access through the application context

package au.com.blogspot.ojitha.spring3tut1;

import javax.inject.Inject;

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

@Component("parent")
public class Parent {
@Inject
//@MyChildQualifier
@GrandChildQualifier
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();

}

}

The Parent component named as “parent”.

The GrandChild component is as follows

package au.com.blogspot.ojitha.spring3tut1;

import org.springframework.stereotype.Component;

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

With only qualifier, it should be possible to find the component. Obviously, this is possible with <context:include-filter> and <context:exclude-filter>. For example, remove the @component from the GrandChild bean as follows

package au.com.blogspot.ojitha.spring3tut1;


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

You need to remove the component from the MyChild bean also

package au.com.blogspot.ojitha.spring3tut1;


@MyChildQualifier
//@Component
public class MyChild extends Child{
@Override
public void sayHello(){
System.out.println("Hello");
}

}

Now if you look at carefully in the spring-config.xml file

<?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:component-scan base-package="au.com.blogspot.ojitha.spring3tut1">
<context:include-filter type="assignable" expression="au.com.blogspot.ojitha.spring3tut1.Child"/>
</context:component-scan>

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

In the spring-config.xml, all the beans of type “au.com.blogspot.ojitha.spring3tut1.Child” is assignable that means both MyChild an GrandChild are auto discovered as components.

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