SpringTechnology

Spring Setter Dependency Injection Example

Learn how to write Spring Setter Dependency Injection Example. The Setter Injection is a type of Spring Dependency Injection. Spring supports Field Injection, Setter Injection as well as Constructor injection to inject dependencies in a Spring managed bean. Scope of this tutorial is limited to Setter Injections.

What is Spring Setter Injection?

Spring Setter Injection is nothing but injecting the Bean Dependencies using the Setter methods on an Object. Unlike Spring Constructor Injection, in Setter Injection, the object is created first and then the dependency is injected.

Consider, we have a DogsService, which is a Spring based REST Service.

We will write a DogsController, DogsService, and a DogsDao. This is a dummy service which does nothing. Intention here is to see how the Spring Dependency Injection works with Setter methods.

Don’t know how to write Spring Boot Rest Service?
Read this: Spring Boot Rest Service

Want to learn more about Spring Framework ?
Read this:

DogsDao.java

There are no fields hence no dependency. We have added a no-argument constructor with a print message.

package com.amitph.spring.dogs.dao;

import com.amitph.spring.dogs.repo.Dog;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class DogsDao {
    public DogsDao(){
        System.out.println("DogsDao no-arg constructor called");
    }
    public List<Dog> getAllDogs() {
        System.out.println("DogsDao.getAllDogs called");
        return null;
    }
}

DogsService.java

The DogsService depends on DogsDao. In the class below the setter method is annotated with @Autowired. To see how the Setter Injection works we have added a print statement in the setter method. Along with a setter method, we have also added a no-argument constructor and a parameterised constructor with respective print messages.

package com.amitph.spring.dogs.service;

import com.amitph.spring.dogs.dao.DogsDao;
import com.amitph.spring.dogs.repo.Dog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class DogsService {
    private DogsDao dao;

    public List<Dog> getDogs() {
        System.out.println("DogsService.getDogs called");
        return dao.getAllDogs();
    }

    @Autowired
    public void setDao(DogsDao dao) {
        System.out.println("DogsService setter called");
        this.dao = dao;
    }

    public DogsService(){
        System.out.println("DogsService no-arg constructor called");
    }
    public DogsService(DogsDao dao) {
        System.out.println("DogsService arg constructor called");
        this.dao = dao;
    }
}

DogsController.java

The DogsController depends upon DogsService. The setter is annotated with @Autowired and has a print statement. Along with the setter method, we have also added a no-argument and a parameterised constructor along with respective print messages.

package com.amitph.spring.dogs.web;

import com.amitph.spring.dogs.repo.Dog;
import com.amitph.spring.dogs.service.DogsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/dogs")
public class DogsController {
    private DogsService service;

    @GetMapping
    public List<Dog> getDogs() {
        return service.getDogs();
    }

    @Autowired
    public void setService(DogsService service) {
        System.out.println("DogsController setter called");
        this.service = service;
    }
}

Application Startup

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.0.RELEASE)

2019-02-04 19:06:17.058  INFO 68545 --- [           main] com.amitph.spring.dogs.Application       : Starting Application on Amitsofficemac.gateway with PID 68545 (/Users/aphaltankar/Workspace/personal/dog-service-jpa/out/production/classes started by aphaltankar in /Users/aphaltankar/Workspace/personal/dog-service-jpa)
2019-02-04 19:06:17.061  INFO 68545 --- [           main] com.amitph.spring.dogs.Application       : No active profile set, falling back to default profiles: default
2019-02-04 19:06:17.670  INFO 68545 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2019-02-04 19:06:17.724  INFO 68545 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 48ms. Found 1 repository interfaces.
2019-02-04 19:06:17.992  INFO 68545 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$4a5366ed] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-02-04 19:06:18.225  INFO 68545 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-02-04 19:06:18.237  INFO 68545 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-02-04 19:06:18.237  INFO 68545 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/9.0.12
2019-02-04 19:06:18.242  INFO 68545 --- [           main] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/aphaltankar/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
2019-02-04 19:06:18.315  INFO 68545 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-02-04 19:06:18.315  INFO 68545 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1205 ms
2019-02-04 19:06:18.339  INFO 68545 --- [           main] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
2019-02-04 19:06:18.342  INFO 68545 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2019-02-04 19:06:18.342  INFO 68545 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2019-02-04 19:06:18.342  INFO 68545 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'formContentFilter' to: [/*]
2019-02-04 19:06:18.342  INFO 68545 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2019-02-04 19:06:18.434  INFO 68545 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2019-02-04 19:06:18.524  INFO 68545 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2019-02-04 19:06:18.645  INFO 68545 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
	name: default
	...]
2019-02-04 19:06:18.690  INFO 68545 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.3.7.Final}
2019-02-04 19:06:18.691  INFO 68545 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
2019-02-04 19:06:18.779  INFO 68545 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
2019-02-04 19:06:18.868  INFO 68545 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect
2019-02-04 19:06:19.279  INFO 68545 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
DogsDao no-arg constructor called
DogsService no-arg constructor called
DogsService setter called
DogsController no-arg constructor called
DogsController setter called
2019-02-04 19:06:19.650  INFO 68545 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-02-04 19:06:19.681  WARN 68545 --- [           main] aWebConfiguration$JpaWebMvcConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2019-02-04 19:06:19.856  INFO 68545 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-02-04 19:06:19.859  INFO 68545 --- [           main] com.amitph.spring.dogs.Application       : Started Application in 3.138 seconds (JVM running for 3.647)

What happened here is the Spring first tried to instantiate DogsController and found a dependency over DogsService. Hence, it went to instantiate DogsService, which in-turn has a dependency over DogsDao. Hence the DogsDao is the first to get instantiated, then DogsService and finally the DogsController.

Let’s see what happened in detail.

  • Line #36: No-argument constructor of DogsDao is called.
  • Line #37: No-argument constructor of DogsService is called. Note: the parameterised constructor never got called.
  • Line #38: Setter of DogsService is called. Where instance of DogsDao (created at line #36) is injected.
  • Line #39: No-argument constructor of DogsController is called.
  • Line #40: Setter of DogsController is called. The DogsService instance (created in line #37) is injected.

The log shows that the objects get created first and then the dependency is injected. Very similar to Setter Injection Spring also supports Field Injection. The Spring Field Injection based on setting the fields directly using Java Reflections API.

Summary

You learnt How to write a Setter Injection in a Spring Application. In case of Setter Injection, the setter methods are annotated with @Autowired. Spring will first use the no-argument constructor to instantiate the bean and then call setter methods to inject the dependencies.

In the coming tutorial we will see Spring Constructor Injection Example.

Leave a Reply

Your email address will not be published. Required fields are marked *