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

Parse the namespace based XML using Python

How To: GitHub projects in Spring Tool Suite

EJB 3 JUnit testing with OpenEJB 3.1.4