Dependency injection in Spring

Because DI is at the core of the Spring Framework, let's spend some time understanding how it works in Spring. We will create a standalone application for this purpose. Create a simple Maven project. Add the following dependency for the Spring Framework:

    <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-context</artifactId> 
      <version>5.0.5.RELEASE</version> 
    </dependency> 

Replace the preceding version number with the latest version of Spring. Classes managed by the DI container of Spring are called beans or components. You can either declare beans in an XML file or you can annotate the class. We will use annotations in this chapter. However, even though we use annotations, we need to specify the minimum configuration in an XML file. So, create an XML file in the src/main/resource folder of your project and name it context.xml. The reason that we are creating this file in the src/main.resource folder is that the files in this folder are made available in the classpath. Next, add the following content to context.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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="packt.jee.eclipse.spring"/>
</beans>

By using the <context:component-scan> tag, we are telling the Spring Framework to scan the base-package folder and then look for the classes annotated with @Component and recognize them as managed classes so that they can be made available when injecting dependencies. In the preceding example, all classes in the packt.jee.eclipse.spring package (and its sub-packages) would be scanned to identify components.

Information read from the configuration file must be saved in an object. In Spring, it is saved in an instance of the ApplicationContext interface. There are different implementations of ApplicationContext. We will be using the ClassPathXmlApplicationContext class, which looks for the configuration XML file in the classpath.

We will now create two Spring components. The first one is CourseDAO, and the second is CourseService. Although we won't write any business logic in these classes (the purpose of this example is to understand how DI works in Spring), assume that CourseDAO could have the code to access the database and CourseService calls CourseDAO to perform the database operations. So, CourseService is dependent on CourseDAO. To keep the code simple, we will not create any interface for CourseDAO but will have the direct dependency. Create the CourseDAO class as follows:

package packt.jee.eclipse.spring; 
 
import org.springframework.stereotype.Component; 
 
@Component 
public class CourseDAO { 
 
} 

We will have no methods in CourseDAO, but as mentioned before, it could have methods to access the database. @Component marks this class as managed by Spring. Now, create the CourseService class. This class needs an instance of CourseDAO:

package packt.jee.eclipse.spring; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 
 
@Component 
public class CourseService { 
 
  @Autowired 
  private CourseDAO courseDAO; 
 
  public CourseDAO getCourseDAO() { 
    return courseDAO; 
  } 
} 

We have declared a member variable called courseDAO and annotated it with @Autowired. This tells Spring to look for a component in its context (of CourseDAO type) and assign that to the courseDAO member.

We will now create the main class. It creates ApplicationContext, gets the CourseService bean, calls the getCourseDAO method, and then checks whether it was injected properly. Create the SpringMain class:

package packt.jee.eclipse.spring; 
 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext; 
 
public class SpringMain { 
 
  public static void main (String[] args) { 
    //create ApplicationContext 
    ApplicationContext ctx = new 
ClassPathXmlApplicationContext("context.xml"); //Get bean CourseService courseService = (CourseService)
ctx.getBean("courseService"); //Get and print CourseDAO. It should not be null System.out.println("CourseDAO = " +
courseService.getCourseDAO()); } }

We first create an instance of ClassPathXmlApplicationContext. The configuration XML file is passed as an argument to the constructor. We then get the courseService bean/component. Note the naming convention when specifying the bean name; it is the class name with the first letter in lowercase. We then get and print the value of CourseDAO. The value won't show any meaningful information, but if the value is not null, then it would mean that the Spring DI container has injected it properly. Note that we have not instantiated CourseDAO; it is the Spring DI container that instantiates and injects this object.

In the preceding code, we saw an example of injecting objects at the member declaration (this is also called property injection). We can have this object injected in the constructors too:

@Component 
public class CourseService { 
 
  private CourseDAO courseDAO; 
 
  @Autowired 
  public CourseService (CourseDAO courseDAO) { 
    this.courseDAO = coueseDAO; 
  } 
 
  public CourseDAO getCourseDAO() { 
    return courseDAO; 
  } 
} 

Note that the @Autowired annotation is moved to the constructor, and the single constructor argument is auto-injected. You can also have the object injected in a setter:

@Component 
public class CourseService { 
 
  private CourseDAO courseDAO; 
 
  @Autowired 
  public void setCourseDAO (CourseDAO courseDAO) { 
    this.courseDAO = courseDAO; 
  } 
 
  public CourseDAO getCourseDAO() { 
    return courseDAO; 
  } 
} 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.102.50