Why does IDEA warn when using @Autowired?

When using IDEA to write Spring-related projects, when using the @Autowired annotation on a field, a wavy line prompt will always appear: "Field injection is not recommended." This makes me wonder: I use this method every day. , why is it not recommended? Today, I decided to dig deeper into why.

As we all know, the Spring framework provides three optional dependency injection methods: constructor injection, Setter method injection and Field injection. Here, we will explore the usage scenarios of these three injection methods in detail.

constructor injection

As shown below, when using constructor injection, we can set the property field to final. Through constructor injection, when AService is instantiated, the BService object must be initialized in advance to ensure that the injected object must not be null. Constructor injection is suitable for scenarios where there are strong dependencies between objects, but it cannot solve the problem of circular dependencies (because they must rely on each other to complete initialization, resulting in conflicts that cannot be resolved).

Regarding the issue of circular dependencies, it is recommended to read What are Spring circular dependencies and how to solve them  . This article will explain in more depth the principles and solutions to circular dependencies in Spring.

@Service
public class AService {
    private final BService bService;
​
    @Autowired  //spring framework 4.3之后可以不用在构造方法上标注@Autowired
    public AService(BService bService) {
        this.bService = bService;
    }
}

Setter method injection

When using the Setter method for injection, Spring will call the Setter method to inject dependencies after executing the default no-argument constructor to instantiate the Bean object. In this way, we can set the "required" attribute to false, which means that if the injected Bean object does not exist, Spring will directly skip the injection without reporting an error.

@Service
public class AService {
    private  BService bService;
​
    @Autowired(required = false)
    public void setbService(BService bService) {
        this.bService = bService;
    }
}

Field injection

Indeed, Field injection is visually very simple and beautiful, so it is widely adopted. When using Field injection, the Spring container will use the reflection mechanism to set the fields that need to be injected after the object is instantiated.

@Service
public class AService {
    @Autowired
    private  BService bService;
}

Why IDEA does not recommend using Field injection

After consulting various sources, I found the following important reasons why Field injection may not be recommended:

  1. May cause null pointer exception: If the object is created without using the Spring container, but directly uses the parameterless constructor method new to create an object, using the injected object may cause a null pointer exception.
  2. Cannot use final modified fields: The lack of final modification will make the dependencies of the class variable, which may cause some unpredictable exceptions. Normally, you can use constructor injection to declare beans with mandatory dependencies, and use setter method injection to declare beans with optional dependencies.
  3. Might be easier to violate the Single Responsibility Principle: this is a key reason. Using field injection may easily introduce various dependencies into a class, causing the class to have too many responsibilities, but it is often difficult for developers to detect it. In contrast, using constructor injection, when the constructor has too many parameters, the developer will be prompted to refactor the class.
  4. Not conducive to writing unit tests: In unit tests, when using Field injection, reflection must be used to Mock dependent objects.

To solve these problems, we can use the following alternatives:

  • When a class has strong dependencies on other beans, constructor injection is preferred.
  • For optional dependencies, you can use Setter method injection and handle possible situations where the referenced object does not exist in your code.

Spring official attitude

The Spring official documentation does not explicitly discuss field injection in the dependency injection section, but places more emphasis on constructor method injection and Setter method injection. Constructor injection is considered the preferred method of dependency injection because it ensures that dependent objects are injected when they are created, thereby avoiding potential problems such as null pointer exceptions and class mutability.

Setter method injection is also useful in optional dependency scenarios, but developers need to handle the situation when the dependent object does not exist.

Overall, the Spring team strongly recommends using constructor injection as it is safer and more reliable in many ways. At the same time, choosing the appropriate dependency injection method can also be used flexibly according to specific situations.

Summarize

When using dependency injection in Spring, constructor injection is preferred. Although constructor injection cannot solve the problem of circular dependencies, when circular dependencies occur, we should give priority to whether there are problems with the code structure design. Of course, it does not rule out certain scenarios where circular dependencies must be used, in which case field injection may come in handy.

Finally, I want to emphasize that when using IDEA, it is important to pay attention to the reminders that the code is underlined or yellowed. These tips can help us learn from the best practices summarized by others and improve our own coding skills.

This article was first published: https://www.panziye.com/java/7639.html

Thanks for the support!

Guess you like

Origin blog.csdn.net/mixika99/article/details/132311859