The main types of dependency injection
- Constructor injection
- Setter injection
- Interface injection (not recommended)
- Field variable injection (not recommended)
Setter injection battle constructor injection
-
Constructor injection
Spring 4.x will encourage the use of constructor injection, and constructor-injected components usually need to be initialized at construction time. That is, normally dependent components and external inputs that components depend on need to be initialized at construction time.
-
When implementing a business component, constructor injection ensures that the object is not null if it is an immutable object. That is, when relying on an object, the object must exist and therefore cannot be null. Even if the object does not exist or is really empty, it can be returned via the getIfAvailable() method of ObjectProvider (a type-safe way introduced by Spring 4.x).
-
Advantages of constructor injection:
- Constructor injection allows fields that would normally not change, and assigned fields to be defined as final, which is friendly both from a thread-safety perspective and from a future variability perspective. It is common practice in object orientation that an object is immutable, that is, once it is created, it does not change. If the object is to change, it can be regenerated, using the newly generated object instead of the old object.
- When you use more than one Java Bean, there is a little less code, mainly in terms of Setter/getter methods.
- Constructor injection is constrained by the order in which it is initialized according to Java syntax, and cannot be modified by the client.
-
If the constructor injection has too many arguments, the code doesn’t look very friendly and generally needs some refactoring. In other words, you shouldn’t put too much responsibility into a class, and you shouldn’t have too much input into a method.
// Constructor infuses private DependencyA DependencyA; private DependencyB dependencyB; private DependencyC dependencyC; @Autowired public DependencyInjection(DependencyA dependencyA, DependencyB dependencyB, DependencyC dependencyC) { this.dependencyA = dependencyA; this.dependencyB = dependencyB; this.dependencyC = dependencyC; }Copy the code
-
Setter injection
Spring3.X encourages use, and Spring 4.X later considers it optional. Setter injection fields themselves are mutable, so the object itself or the injected content can be null. The @AutoWired annotation, for example, forces the dependency to be injected by default. If the dependency does not exist, it is controlled by setting the attribute required(which defaults to true) to false.
// Do not pass any arguments to the age attribute. The following example will work successfully, but the name attribute requires a single argument. private String name; @Autowired(required=false) public void SetAge(Integer age) { this.age = age; } @Autowired public void SetName(String name) { this.name = name; }}Copy the code
Advantages and disadvantages of Setter injection
- Setter methods usually make objects more configurable or can be reinjected at some point. In other words, when a dependency is injected, it may be injected for the first time, and then injected again, there will be no change to a new object.
- Setter injection works very well for objects with default values, meaning that not all properties need to be provided at run time. Object has a default value, and Setter methods override that initial value.
- There is no order in the Setter. For example, the Student object has SetAge/SetName methods, and there is no convention on which comes first or which comes later.
- Injection of setters, it only helps us inject dependencies when the object needs to be injected, not when it’s initialized
// implement private DependencyA DependencyA; private DependencyB dependencyB; private DependencyC dependencyC; @Autowired public void setDependencyA(DependencyA dependencyA) { this.dependencyA = dependencyA; } @Autowired public void setDependencyB(DependencyB dependencyB) { this.dependencyB = dependencyB; } @Autowired(required=false) public void setDependencyC(DependencyC dependencyC) { this.dependencyC = dependencyC; }Copy the code