Printable Version Printable Version

Spring 3.0 – Java Annotation based Dependency Injection(DI)

Jan 19th, 2010 | By admin | Category: Spring

If you have been using Spring Framework for sometime , you will be aware that the Spring Framework has undergone several major changes in the latest Spring version 3.x. Spring Framework is now based on Java 5 and Java 6 fully supported. It has incorporated all the important features of Java latest versions. Spring version 3.0 encourages the developers to use Java Annotations instead of the configuration xml. This post will talk on the Annotation based Dependency Injection mechanism using Spring 3.0.

In my one of the post I have discussed on setter injection using Spring 2.5(old method). Going through that post will help you to find the difference between these two dependency injection approach. Lets get started.

What is Dependency Injection ? The answer is , It is a Design Pattern. Inversion of control or dependency injection pattern used to resolve component dependencies by injecting an instantiated component to satisfy dependency as opposed to explicitly requesting a component. So components will not be explicitly requested but components are provided as needed with the help of an Inversion of controller containers. Please read the post to know more on it.

Spring has a concept of instantiated component , i.e , bean. Previously , we used to configure bean in the Application Context xml file but with Spring 3.0 , we will be configuring bean and injecting services(dependencies) from our java classes. Lets do it with an example use case.

Have a look at the following class relations


Class Relation

Class Relation

Use Case : OpsClient is a normal Java Class which is registered with two services , i.e , Calculator Service and Print Service. Calculator Service is an interface to different calculation services available , like , addition , multiplication etc. Print Service is another interface to different printing services available , like , printing to a file or printing to console etc. The OpsClient makes use of these different services to perform different calculation and print them on different printing interfaces.

Approach with Spring 3.0 :

CalculatorService and PrintService are two interfaces. AddCalculatorServiceImpl , MultiplyCalculatorServiceImpl are the implementation of CalculatorService interface and ConsolePrintServiceImpl , FilePrintServiceImpl are the implementation of the PrintService interface. Hence , these implementation classes are the beans in Spring. Lets define them one by one.

Listing 1 : CalculatorService.java Interface

package com.company.spring.basic.service;

public interface CalculatorService {

	public long calculate(long x,long y);
	public String getOperationName();

}

Listing 2 : PrintService.java Interface

package com.company.spring.basic.service;

public interface PrintService {

	public void print(String result);
}

Lets define all the implementation (beans) of the services

Listing 3 : AddCalculatorServiceImpl.java

package com.company.spring.basic.service.impl;

import javax.inject.Named;

import com.company.spring.basic.service.CalculatorService;
@Named("AddCalcService")
public class AddCalculatorServiceImpl implements CalculatorService {

	@Override
	public long calculate(long x, long y) {
		return x+y;
	}

	@Override
	public String getOperationName() {
		return " plus ";
	}
}

Listing 4 : MultiplyCalculatorServiceImpl.java

package com.company.spring.basic.service.impl;

import javax.inject.Named;

import com.company.spring.basic.service.CalculatorService;
@Named("MultiplyCalcService")
public class MultiplyCalculatorServiceImpl implements CalculatorService {

	@Override
	public long calculate(long x, long y) {

		return x*y;
	}

	@Override
	public String getOperationName() {

		return " multiplies ";
	}
}

Listing 5 : ConsolePrintServiceImpl.java

package com.company.spring.basic.service.impl;

import javax.inject.Named;

import com.company.spring.basic.service.PrintService;
@Named("ConsolePrintService")
public class ConsolePrintServiceImpl implements PrintService {

	@Override
	public void print(String result) {
		System.out.println(result);

	}
}

Listing 6 : ConsolePrintServiceImpl.java

package com.company.spring.basic.service.impl;

import javax.inject.Named;

import com.company.spring.basic.service.PrintService;

@Named("FilePrintService")
public class FilePrintServiceImpl implements PrintService{

	@Override
	public void print(String result) {
          // Code to write to a file
	}
}

Listing 3 – Listing 6 shows the normal but special implementation of the interfaces. They are special , because they are to support the Spring Framework’s Bean concept. To do that , each of this implementation is annotated with @Named(”SomeName”) annotation. In Spring 3.x you can use JSR 330’s @Named annotation in place of stereotype annotations and they will be automatically detected during component-scanning.
The value of the @Named property will be used as the Bean Name. At this time Spring defaults for bean
scope will be applied when using @Named.

This annotation will be available if if the JSR330 jar is present on the classpath. This jar is not part of the Spring 3.0 download. It is available under SpringSource Enterprise Bundle Repository. This annotation will be available under the com.springsource.javax.inject-1.0.0.jar. You can find the other jars here.

The next task is to build the Application context. Wait , we are not going to build any xml file here. It is going to be a simple Java class annotated with some useful annotations. Have a look at the following code.

Listing 7 : ApplicationConfig.java

package com.company.spring.basic;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.company.spring.basic.client.OpsClient;
import com.company.spring.basic.service.CalculatorService;
import com.company.spring.basic.service.PrintService;
import com.company.spring.basic.service.impl.AddCalculatorServiceImpl;
import com.company.spring.basic.service.impl.ConsolePrintServiceImpl;
import com.company.spring.basic.service.impl.FilePrintServiceImpl;
import com.company.spring.basic.service.impl.MultiplyCalculatorServiceImpl;

@Configuration
public class ApplicationConfig {
	@Bean
	public PrintService screnPrint(){
		return new ConsolePrintServiceImpl();
	}
	@Bean
	public PrintService filePrint(){
		return new FilePrintServiceImpl();
	}
	@Bean
	public CalculatorService add(){
		return new AddCalculatorServiceImpl();
	}
	@Bean
	public CalculatorService Multiply(){
		return new MultiplyCalculatorServiceImpl();
	}
	@Bean
	public OpsClient result(){
		return new OpsClient();
	}
}

The class is annotated with @Configuration annotation. Annotating a class with the @Configuration indicates that the class can be used by the Spring IoC container as a source of bean definitions. These classes(@ Configuration annotated) consist principally of @Bean-annotated methods that define instantiation,configuration, and initialization logic for objects to be managed by the Spring IoC container.

To declare the beans , we have created methods and annotated with the @Bean annotation. The @Bean annotation plays the same role as the element.When @Configuration classes are provided as input, the @Configuration class itself is registered as a bean definition, and all declared @Bean methods within the class are also registered as bean definitions.

So we have five beans declared all together. The last bean declared is the OpsClient bean which has two references , i.e , CalculatorService and PrintService(Please refer to the Class Relations diagram above). We will achieve this reference injection with the help of a very special annotation @Inject. Have a look.

Listing 8 : OpsClient.java

package com.company.spring.basic.client;

import javax.inject.Inject;
import javax.inject.Named;
import com.company.spring.basic.service.CalculatorService;
import com.company.spring.basic.service.PrintService;

public class OpsClient {

	@Inject
	@Named("FilePrintService")
	private PrintService printService;

	@Inject
	@Named("MultiplyCalcService")
	private CalculatorService calculatorService;

	public void execute(long op1,long op2)  {
		printService.print("The result of " + op1 +
				calculatorService.getOperationName() + op2 + " is "
	   			+ calculatorService.calculate(op1, op2) + "!");

	}
}

printService and the calculatorCulatorService are the references to the different service implementations which can be injected using the @Inject annotation and @Named annotations. Here @Named annotation work as a mapping of service implementations. The name supplied as a parameter to the @Named annotation should be matched with one of the service implementation annotated with the same @Named annotation.

Like @Named , @Inject annotation can be found under the same package javax.inject.Inject. In the above class we are injecting the multiplication calculator service and the file print service using the annotations. Now the only thing pending is to instantiate the Application Context and call the client. It is explained below ,

Listing 9 : OperationTest.java

public class OperationTest {
	public static void main(String[] args) {
		ApplicationContext ctx = new AnnotationConfigApplicationContext(
				com.company.spring.basic.ApplicationConfig.class);
		OpsClient opsBean = ctx.getBean(OpsClient.class);
		opsBean.execute(2, 3);
	}
}

Once you run the above method , multiplication of the value 2 and 3 will be written in a file.

You would need to add the following jar files to the class-path ,
- cglib-nodep-2.1_3.jar
- classworlds-1.1-alpha-2.jar
- com.springsource.javax.inject-1.0.0.jar
- com.springsource.javax.inject-sources-1.0.0.jar
- jcl-over-slf4j-1.5.10.jar
- log4j-1.2.15.jar
- slf4j-api-1.5.10.jar
- slf4j-log4j12-1.5.10.jar
- spring-aop-3.0.0.RELEASE.jar
- spring-asm-3.0.0.RELEASE.jar
- spring-beans-3.0.0.RELEASE.jar
- spring-context-3.0.0.RELEASE.jar
- spring-core-3.0.0.RELEASE.jar
- spring-expression-3.0.0.RELEASE.jar
- spring-jdbc-3.0.0.RELEASE.jar
- spring-tx-3.0.0.RELEASE.jar

Most of the above jars can be downloaded as part of Spring 3.x download. Other jars can be found here.

  • Share/Save/Bookmark
Tags: , ,

7 comments
Leave a comment »

  1. Класс! Афтару респект!

  2. большое спасибо!Взяла себе тоже-пригодится.

  3. Nice one. Keep posting more.

  4. Спасибо!, в цитатник!

  5. :-) ))))))))))))))))))))))))))

  6. uponogepywev…

    Frankie Sandford

  7. Genial brief and this enter helped me alot in my college assignement. Thanks you on your information.

Leave Comment