SoFunction
Updated on 2025-04-14

The difference and description of SpringBoot field injection and constructor injection

Article background

When using Spring development projects, we often need to use dependency injection to manage dependencies between objects. Spring provides a variety of dependency injection methods, such as constructor injection, Setter method injection and field injection.

These methods have their own advantages and disadvantages, and it is necessary to choose a suitable injection method according to the specific situation.

In this article, I will share some of the problems I encountered during the development process, as well as my thoughts and solutions to these problems.

It mainly involves the following aspects:

  • Differences and connections between field injection and constructor injection
  • Why field injection and Setter method injection do not cause circular dependencies, while constructor injection causes circular dependencies
  • Why does Spring not recommend field injection, but constructor injection is recommended

Through this article, I hope it can help you better understand the principles and practices of Spring's dependency injection, as well as how to avoid some common problems and errors.

What are field injection and constructor injection?

In SpringBoot we can use@AutowiredAnnotation to implement dependency injection, that is, let Spring containers automatically provide the required objects for our class.

There are three common injection methods: field injection.SetterMethod injection andConstructorinjection.

  • Field injection: Use directly on the properties of the class@AutowiredAnnotation, no need to write extra code.
  • Setter method injection: Use on the Setter method of the class@AutowiredAnnotations need to be writtenSettermethod.
  • Constructor injection: Used on the constructor of the class@AutowiredAnnotation requires writing the corresponding constructor.

Here is a simple example, suppose we have oneUserServiceInterface and oneUserServiceImplImplementation class, and aUserControllerClass, we want toUserControllerUsed inUserServiceObject.

// UserService interfacepublic interface UserService {
    void saveUser(User user);
}

// UserServiceImpl implementation class@Service
public class UserServiceImpl implements UserService {
    @Override
    public void saveUser(User user) {
        // Save the user to the database    }
}

// UserController class@Controller
public class UserController {
    // Field injection    @Autowired
    private UserService userService;

    // Setter method injection    // private UserService userService;
    // @Autowired
    // public void setUserService(UserService userService) {
    //      = userService;
    // }

    // Constructor injection    // private final UserService userService;
    // @Autowired
    // public UserController(UserService userService) {
    //      = userService;
    // }

    public void createUser(User user) {
        (user);
        // Other logic    }
}

What is the difference between these two methods?

There is no difference in functionality between these two methods, and both can implement dependency injection. However, there are some differences in some details, mainly the following points:

  • Readability: Field injection code is cleaner, dependencies are isolated in one place, making it easier to read. The code injected by the constructor is more verbose, and the constructor can become bloated when there are multiple dependencies.
  • Invariance: Constructor injection supports invariance, that is, the dependencies can be declared as final type to ensure that the object will not be modified after creation. This facilitates thread safety, state safety and readability. Field injection does not support invariance, and dependencies cannot be declared as final type.
  • State security: Constructor injection ensures that the object is instantiated into a complete state or not instantiated at all. If the consumer creates an object using the new keyword, all dependencies must be provided as parameters. Field injection cannot guarantee state security. If the user creates an object using the new keyword, the state of the object cannot be set. The only option is to set the private field with reflection.
  • Circular dependency: Circular dependency refers to two or more classes relying on each other, resulting in the inability to create objects normally. For example, if Class A depends on Class B and Class B depends on Class A, a circular dependency will occur. Circular dependence is a bad design pattern that should be avoided.

The connection between field injection and Setter method injection

Field injection and Setter method injection are both implemented through reflection, and they can be used on the properties of the class.@AutowiredAnnotation to annotate dependencies.

The difference is that field injection is used directly on the attribute@AutowiredAnnotation, and Setter method injection is used on the Setter method corresponding to the attribute@Autowiredannotation.

There are several points in the connection between field injection and Setter method injection:

  • They all match dependencies based on names or types. If the attribute name or Setter method name is the same as the id or name in the Bean definition, it will be matched according to the name; otherwise, it will be matched according to the attribute type or Setter method parameter type.
  • None of them supports invariance, i.e. the dependency cannot be declared as final type. This can lead to issues with thread safety, state safety and readability.
  • They both avoid the problem of circular dependencies because they are injected only after the object is created, not when the object is created. This avoids possible circular dependency exceptions during constructor injection.

Why does field injection and Setter method injection not cause problems with circular dependencies?

Circular dependence refers to two or more classes relying on each other, causing the object to be created normally. For example, if Class A depends on Class B and Class B depends on Class A, a circular dependency will occur. Circular dependence is a bad design pattern that should be avoided.

In Spring, circular dependencies mainly occur in the case of constructor injection, because constructor injection is used for dependency injection when the object is created, not after the object is created. This will lead to a deadlock, that is, Class A has to wait for Class B to be created before it can be created, and Class B has to wait for Class A to be created before it can be created.

Field injection and Setter method injection do not cause problems with circular dependencies because they are only injected after the object is created, not when the object is created. This can avoid deadlocks, that is, both Class A and Class B can be created first, and then injected into each other.

Spring solves circular dependencies by exposing the early-Stage Object. A semi-finished object refers to an object that has been instantiated but has not been initialized yet. Spring will put the semi-finished object into a cache. When other objects need to rely on it, they can get it from the cache and perform subsequent attribute assignment and initialization operations.

Briefly describe the process of the two methods

The process of field injection and constructor injection is as follows:

  • Field injection: When an IOC container creates a bean, it will first call the parameterless constructor through reflection to instantiate the object, then obtain the @Autowired annotation on the property through reflection, and match the dependency according to the name or type, and finally inject the dependency into the property through reflection.
  • Constructor injection: When an IOC container creates a bean, it will first obtain the @Autowired annotation on the constructor through reflection, and match the dependency according to the name or type, and then instantiate the object through reflection call the constructor with parameter, and pass the dependency as a parameter in.

Why does Spring not recommend field injection?

There are several reasons why Spring does not recommend field injection:

  • Field injection violates the single responsibility principle because it makes it very easy to add new dependencies without causing warnings. This may result in the class having too many responsibilities and concerns that require further inspection and reconstruction.
  • Field injection hides dependencies because it does not use a public interface (method or constructor) to communicate clearly with dependencies. This is not conducive to the testability and reusability of the class, nor is it conducive to the distinction between selectability and mandatory nature of dependencies.
  • Field injection causes coupling of dependency injection containers because it prevents the class from running independently from the container. This means that classes cannot be created through the new keyword, nor can they switch to other dependency injection frameworks.
  • Field injection does not support invariance because it cannot declare dependencies as final type, nor can it inject static variables. This can lead to issues with thread safety, state safety and readability.

Summarize

Field injection and constructor injection are common dependency injection methods in Spring. They each have their own advantages and disadvantages. Developers should choose the appropriate injection method according to the specific situation.

Generally speaking, the following points can be used as reference:

  • If the dependency is required and does not require reconfiguration or reinjection, constructor injection is recommended because it can support invariance and state security.
  • If dependencies are optional or need to be reconfigured or reinjected, field injection or Setter method injection is recommended because they can improve the simplicity and flexibility of the code.
  • If there is a problem with circular dependencies, you cannot use constructor injection, you can only use field injection or Setter method injection, because they can avoid deadlocks.

The above is personal experience. I hope you can give you a reference and I hope you can support me more.