Spring three injection methods, construction, Setter and field injection. Defects based on field injection: final modification, covering up a single responsibility, tight coupling with IOC, hidden dependencies, and no security check

  • Original: https://mp.weixin.qq.com/s/H2VWEhtpRuIqCDvrYnIjcA

  • @Autowire and @Resource annotations

  • Use the correct posture, don’t use the wrong one again! !

Field-based dependency injection warning

When I used Idea to write code today, I saw a warning message displayed in the previous project. I checked it and found the following code?

@Autowire
private JdbcTemplate jdbcTemplate;

Prompted warning message

Field injection is not recommended Inspection info: Spring Team recommends:

The method of attribute field injection is not recommended. The problem detected is: Spring team suggestion:”

“Always use constructor based dependency injection in your beans. Always use

Always use constructor-based dependency injection in beans,

assertions for mandatory dependencies”.

Always use assertions on mandatory dependencies”

This paragraph is the suggestion of the Spring working group, roughly translated:

as shown

imageField injection warning

Injection method

While the current documentation on Spring Framework (5.0.3) only defines two main injection types, there are actually three:

If you are learning Spring Boot, then recommend a free tutorial that has been serialized for many years and continues to be updated: http://blog.didispace.com/spring-boot-learning-2x/

Constructor-based dependency injection

public class UserServiceImpl implements UserService{<!-- -->
    private UserDao userDao;
    
    @Autowire
    public UserServiceImpl(UserDao userDao){<!-- -->
        this. userDao = userDao;
    }
}

Setter-based dependency injection

public class UserServiceImpl implements UserService{<!-- -->
     private UserDao userDao;
     
     @Autowire
     public serUserDao(UserDao userDao){<!-- -->
         this. userDao = userDao;
     }
 }

Field-based dependency injection

public class UserServiceImpl implements UserService{<!-- -->
     @Autowire
     private UserDao userDao;
 }

The field-based dependency injection method will get a yellow card warning in Idea, but this method is also the most widely used because it is concise and convenient. You can even see this injection method in some Spring guides, although it is not in the documentation It is recommended to do this. (It feels like law enforcement is breaking the law)

as shown

imageSpring’s own document

Disadvantages of field-based dependency injection

It is not good for variables with final modification

Spring’s IOC uses the set form for attribute injection, but final type variables

  • In the process of calling the class constructor, the initialization must be completed.

This is where Field-Based Dependency Injection cannot do. Only constructor-based dependency injection can be used.

Cover up the design idea of single responsibility

We all know that there is a single responsibility idea in the design of OOP. If you use constructor-based dependency injection to use Spring’s IOC, when When you inject too much, the parameters of this constructor will be very large, similar to the following.

When you see so many parameters in the construction method of this class, you will naturally think: Does this class violate the idea of single responsibility?. But using field-based dependency injection Won’t let you know, you’ll be very immersed in @Autowire

public class VerifyServiceImpl implements VerifyService{<!-- -->
    
  private AccountService accountService;
  private UserService userService;
  private IDService idService;
  private RoleService roleService;
  private PermissionService permissionService;
  private EnterpriseService enterpriseService;
  private EmployeeService employService;
  private TaskService taskService;
  private RedisService redisService;
  private MQService mqService;

  public SystemLogDto(AccountService accountService,
                      UserService userService,
                      IDService idService) {<!-- -->
      this.accountService = accountService;
      this. userService = userService;
      this.idService = idService;
      ...
  }
}

Tightly coupled with Spring’s IOC mechanism

When you use Field-based dependency injection, you can indeed omit template-type methods such as constructors and setters, but you give Spring’s IOC full control strong>,

  • Other classes want to reset one of your injection properties, but can’t handle it (of course reflection can do it).

The purpose of Spring itself is decoupling and dependency inversion. As a result, by coupling with the class injector (Spring in this case) again, the decoupling of the class achieved by auto-assembling the class field is lost, so that Class is not valid outside the Spring container.

Hide dependencies

When you use Spring’s IOC, the injected class should use some public type (construction method, and setter type method) methods to express to the outside world: what dependencies do I need. But Field-based dependency injection method is basically in the form of private, and private seals all the attributes into the class.

Unable to perform security check on injected properties

Field-based dependency injection, you can’t get this class when the program starts, you can only get it when you use it in real business, under normal circumstances, this injection is non-null , What if it is null, the error will only burst out during business processing, the time is a bit late, if it is exposed at startup, then the bug can be fixed quickly (of course you Annotation verification can be added).

If you want to operate something based on the injected object when the attribute is injected, you can’t do it. Examples I have encountered: some configuration information, some people always misconfigure it, and they don’t know that it is misconfigured until they test the business stage.

For example, the initial number of threads is accidentally configured to 3000, and the machine is really screaming! At this time, it is necessary to make a detection mechanism when some Value is injected.

Conclusion

Through the above, we can see that field-based dependency injection has many disadvantages, and we should avoid using field-based dependency injection.

  • The recommended approach is to use constructor-based and setter-based dependency injection. For required dependencies, constructor-based injection is recommended, to make them immutable and prevent them from being null.
  • For optional dependencies, Setter-based injection is recommended

Postscript

Translated from field-injection-is-not-recommended, adding my own vernacular understanding!

syntaxbug.com © 2021 All Rights Reserved.