spring framerwork 3.0<span style="outline: 0px;font-size: 16px;visibility: visible;"></span>
upgraded to 5.0<span style="outline: 0px;font-size: 16px;visibility: visible;"></span>
, and then suddenly discovered when writing code Idea gives a warning prompt on the @Autowired annotation for attribute injection, like the one below, which is quite confusing. After all, it has been written like this for many years.
Field injection is not recommended
I checked the relevant documents and found out that this prompt started to appear after <span style="outline: 0px;font-size: 16px;visibility: visible;">spring framerwork 4.0</span>
. It is not recommended starting from spring 4.0. Use property injection, constructor injection and setter injection are recommended instead.
The following will show the different types of dependency injection that can be used by the spring framework, and the applicable situations of each dependency injection.
2. Type of dependency injection
Although for <span style="outline: 0px;font-size: 16px;">The documentation for spring framerwork 5.1.3</span>
only defines two main types of dependency injection, but there are actually three;
Among them<span style="outline: 0px;font-size: 16px;">Field-based dependency injection</span>
is widely used, but idea or other static code analysis tools will give prompt messages and are not recommended.
You can even see this injection method in some official Spring guides:
In constructor-based dependency injection, the class constructor is marked @Autowired and contains many objects to be injected related parameters.
@Component public class ConstructorBasedInjection { private final InjectedBean injectedBean; @Autowired public ConstructorBasedInjection(InjectedBean injectedBean) { this.injectedBean = injectedBean; } }
Then in the spring official documentation, the @Autowired annotation can also be omitted.
public class SimpleMovieLister { // the SimpleMovieLister has a dependency on a MovieFinder private MovieFinder movieFinder; // a constructor so that the Spring container can inject a MovieFinder public SimpleMovieLister(MovieFinder movieFinder) { this.movieFinder = movieFinder; } // business logic that actually uses the injected MovieFinder is omitted... }
基于构造函数注入的主要优点是可以将需要注入的字段声明为final, 使得它们会在类实例化期间被初始化,这对于所需的依赖项很方便。
在基于setter的依赖注入中,setter方法被标注为 @Autowired。一旦使用无参数构造函数或无参数静态工厂方法实例化Bean,为了注入Bean的依赖项,Spring容器将调用这些setter方法。
@Component public class SetterBasedInjection { private InjectedBean injectedBean; @Autowired public void setInjectedBean(InjectedBean injectedBean) { this.injectedBean = injectedBean; } }
和基于构造器的依赖注入一样,在官方文档中,基于Setter的依赖注入中的 @Autowired也可以省去。
public class SimpleMovieLister { // the SimpleMovieLister has a dependency on the MovieFinder private MovieFinder movieFinder; // a setter method so that the Spring container can inject a MovieFinder public void setMovieFinder(MovieFinder movieFinder) { this.movieFinder = movieFinder; } // business logic that actually uses the injected MovieFinder is omitted... }
在基于属性的依赖注入中,字段/属性被标注为 @Autowired。一旦类被实例化,Spring容器将设置这些字段。
@Component public class FieldBasedInjection { @Autowired private InjectedBean injectedBean; }
正如所看到的,这是依赖注入最干净的方法,因为它避免了添加样板代码,并且不需要声明类的构造函数。代码看起来很干净简洁,但是正如代码检查器已经向我们暗示的那样,这种方法有一些缺点。
3. Field-based dependency injection defects
Field-based dependency injection does not work on fields declared as final/immutable because these fields must Instantiated when the class is instantiated. The only way to declare immutable dependencies is to use constructor-based dependency injection.
##In object-oriented programming, the five design principles SOLID are widely used application, (generally six design principles in China) to improve code reusability, readability, reliability and maintainability
S inSOLID represents the single responsibility principle, that is, a class should only be responsible for one responsibility, and all services provided by this class should only serve the responsibility it is responsible for.
Using field-based dependency injection, for frequently used classes, over time, we will gradually add more and more dependencies to the class. We are very happy to use it, and it is easy to ignore the class. There are already too many dependencies. But if you use constructor-based dependency injection, as more and more dependencies are added to the class, the constructor will become larger and larger, and we can tell something is wrong at a glance.
Having a constructor with more than 10 parameters is a clear sign that the class has transformed into a large and comprehensive collection of functions and needs to be divided into smaller and easier Maintained blocks.
So, although property injection is not a direct cause of breaking the single responsibility principle, it hides signals and makes it easy for us to ignore them.
The main reason to use field-based dependency injection is to avoid getters and setter's boilerplate code or create a constructor for the class. Ultimately, this means that the only way to set these fields is to instantiate the class through the Spring container and inject them using reflection, otherwise the fields will remain null.
The Dependency Injection design pattern separates the creation of class dependencies from the class itself and transfers this responsibility to the class injection container, allowing program design to be decoupled and adhere to a single responsibility and the dependency inversion principle (equally reliable). Therefore, the decoupling of the class achieved by autowiring fields is eventually lost by coupling it again to the class injection container (Spring in this case), thus rendering the class useless outside the Spring container.
This means that if you want to use your class outside the application container, for example for unit testing, you will be forced to use the Spring container to instantiate your class because there is no other possible way (except reflection) to set autowiring fields.
When using dependency injection, the affected classes should be made clear using the public interface Expose these dependencies by exposing required dependencies in the constructor or optional dependencies using methods (setters). When using field-based dependency injection, these dependencies are essentially hidden from the outside world.
4. Summary
We have See, field-based injection should be avoided whenever possible because it has many disadvantages, no matter how elegant it looks. The recommended approach is to use constructor-based and setter-based dependency injection.
For required dependencies, it is recommended to use constructor-based injection, make them immutable, and prevent them from being null. For optional dependencies, it is recommended to use setter-based injection.
The above is the detailed content of Why do big companies ban the use of @Autowired annotation in Spring Boot projects?. For more information, please follow other related articles on the PHP Chinese website!