Using @Named and @Inject in Spring

The following example illustrates using @Named and @Inject annotations from JSR 330 in spring. These annotations are used to inject dependencies just like @Resource. The advantage of these is that since they are supported by JEE 6 and IoC containers like Google Guice, you can migrate from Spring to them easily.

Note: To work with these annotations, you need the javax-inject.jar file which can be downloaded here. Because this jar file contains the annotations that we will use in this example.

Create a project in eclipse

So, I'll be naming the project as spring1 since this is the first demo. Note that I haven't used STS (Spring Tool Suite) which most will probably be using. Rather, I have just downloaded the required jar files we need to create our project and included them in the library. Therefore, we will be carrying on creating a simple eclipse project and adding the necessary spring jars. I am using Eclipse KEPLER.

  1. File -> New -> Project -> Java Project
  2. Give the project name spring33 and click Finish 
  3. Now, the project is created.
  4. Under the Project Explorer (in the sidebar) you will see spring33. If you aren't able to see Project Explorer, go to Window menu -> Show view -> Project Explorer.
  5. Right click on the spring33 and click Properties
  6. On the left side, click on Java Build Path.
  7. Select the Libraries tab and then click on Add External Jars
  8. Now, add these jar files starting with: spring-beans, spring-context, spring-core, commons-logging, javax-inject
  9. Click on OK and then you are ready

To create a class 

In the Project Explorer, navigate to spring33 and right click on spring33. Then go to New -> Class and give the name of the class as defined below.

To create the xml file 

You can add the xml file anywhere you want. But in all the examples, blogged here (including this), the xml file resides in the src folder. So double click on the spring33 in the Project explorer and then under spring33 you will find src folder. Right click on src and New -> Other. Type xml file under in the text box and hit enter. Give the xml file the name as specified below. Here it is jsr330.xml.

Project structure



MessageProvider bean

This is a class that contains the message property which represents a message.

package spring33;

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

@Named("messageProvider")
public class MessageProvider {

@Named("message")
@Inject
private String message;
   
    public void setMessage(String message)
    {
        this.message=message;
    }
   
    public String getMessage()
    {
        return message;
    }
   
}
 

@Named annotation above the class means that the MessageProvider class is a dependency that needs to be injected or in other words a bean that will be used by another bean as a property. It is much similar to the @Component annotation. It is much similar to creating a bean like this (in xml)

<bean id="messageProvider" class="spring33.MessageProvider">
<property name="message" value="..."/>
</bean>

Next, the @Named above the message means that a bean is defined with the name message in the xml file and @Inject tells that its value should be injected (by reading the definition from the xml file).

Note: Without @Inject the value will not be injected. Because @Named only tells the container that it points to a bean with the given name (message here).
However, as you know, the @Resource annotation unlike this, is equal to both @Named + @Inject i.e.

@Resource("message") is equal to @Named("message") @Inject

MessageRenderer bean

This class contains a single property that takes MessageProvider object and then contains a method to print the message in that object.

package spring33;

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

public class MessageRenderer {

@Named("messageProvider")
@Inject
private MessageProvider messageProvider;

    public void setMessageProvider(MessageProvider messageProvider)
    {
        this.messageProvider=messageProvider;
    }
  
    public MessageProvider getMessageProvider()
    {
        return messageProvider;
    }
  
    public void print()
    {
        System.out.println(messageProvider.getMessage());
    }
}

Here also, the @Named tells the container that a bean is defined with the name messageProvider and @Inject tells to inject that bean here i.e. set that bean object reference to messageProvider.
The print() method prints the message by calling getMessage() in System.out.println()

Main program - SpringPrg.java

package spring33;

import org.springframework.context.support.GenericXmlApplicationContext;

public class SpringPrg {

    @SuppressWarnings("resource")
    public static void main(String args[])
    {
        GenericXmlApplicationContext gc=new GenericXmlApplicationContext("classpath:jsr330.xml");
       
        MessageRenderer renderer=gc.getBean("messageRenderer",MessageRenderer.class);
       
        renderer.print();
    }
   
}
 
Here, the first line creates GenericXmlApplicationContext object pointing to the jsr330.xml file that is present in the src folder. Specifying classpath: prefix means that the file is present in the classpath i.e. src folder. If it is present in another folder in the src (for example src/ding) you would specify.. classpath:ding/jsr330.xml.

The getBean() method of the GenericXmlApplicationContext returns the object of the MessageRenderer created as defined in the xml file. The second parameter MessageRenderer.class skips us from manually typecasting the Object returned to MessageRenderer. I mean, if you use just gc.getBean("messageRenderer"), this method returns the Object which you need to typecast again to call the print() method. This object now contains the property messageProvider. The instance of the MessageProvider is defined with the help of annotations (jsr330 annotations) and the property message (defined in the xml) is also injected into it.

Application context - jsr330.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"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                            http://www.springframework.org/schema/context
                            http://www.springframework.org/schema/context/spring-context-3.0.xsd">
       
        <context:component-scan base-package="spring33"/>
       
        <bean id="message" class="java.lang.String">
            <constructor-arg value="Rama"/>
        </bean>
       
        <bean id="messageRenderer" class="spring33.MessageRenderer"/>
</beans>

The <context:component-scan> scans the given package(s) for bean classes and register them with the application context so that they can be looked up. As per the annotations return in those classes, the bean objects are created. Therefore, now the MessageProvider class is found and then a bean is will be created for that class with the name messageProvider and a value to the property message in it will be injected. The reference that is injected here is named message which is defined in the xml file as you can see.
Now, the MessageProvider object is created.

Next, the messageRenderer bean is defined. As per the annotations defined in the MessageRenderer class, the property messageProvider is injected there.

No comments: