An instance of a method in Spring that initializes a generic class
- 2020-05-30 20:17:53
- OfStack
Let's start with a simple class definition like this for generic types in Java
class Processor<T> {}
If you want to specify a specific type when initializing directly, you can write this
Processor<String> processor = new Processor<>(); //Java 7 Version and above
Initialization of basic generics by Spring
If we want to initialize the class with the Spring container, for example, add an @Named annotation to the class above
@Named
class Processor<T> {
}
At this point we pass
beanFactory.getBean(Processor.class)
What kind of an instance do I get? How does Spring know what specific type to specify? Quite simply, any case of uncertainty is Object. So the Processor instance obtained from the container is equivalent to the Processor instance constructed with the following code
Processor processor = new Processor(); // To be more precise Processor<Object> processor = new Processor<>();
Step 1. What does Spring do with a generic definition that has an upper bound? like
@Named
class Processor<T extends Number> {
}
Similarly,
class Processor<T>
The equivalent of
class Processor<T extends Object>
Therefore, Spring will also use the top-level acceptable type if the specific type is not specified. Spring will create the following object for the above code instance
Processor<Number> processor = new Processor<>();
More complicated, the subtype of the generic is still the case for the generic, as shown in the following code
First, a generic interface is defined
public interface Service<T> {
String process(T t);
}
The Spring container is then asked to initiate the following NumberService instance
@Named
public class NumberService<R extends Number> implements Service<R> {
@Override
public String process(R number) {
return "Process Number: " + number;
}
}
When initializing an NumberService instance, Spring also takes the topmost acceptable type and initializes it with the following code
NumberService<Number> numberService = new NumberService<>();
Last but not least, generic types and generic types, what about Spring?
@Named
public class Processor<T> {
@Inject
Private Service<T> service;
}
How does Spring determine the type T above? Because of the
Service<T> service
The existence of the attribute makes it impossible to imagine that Spring will initialize the Processor instance with the following code
Processor<String> processor = new Processor<>(); //Java 7 Version and above
0
Instead, the specific type of Processor must be injected
Service<T>
The specific type of instance is inferred, depending on what exists in the Spring container
Service<T>
Instance. Let me give you two examples
If there is an initialization in Spring
Processor<String> processor = new Processor<>(); //Java 7 Version and above
1
So in front
Processor<T>
The instance is equivalent to
Processor<String> processor = new Processor<>(); //Java 7 Version and above
2
If it's initialized in Spring
Service<T>
It's the one up front
NumberService<R extends Number> implements Service<R>
So the Spring container
Processor<T>
Instance equivalent
Processor<Number> processor = new Processor<>();
processor.service = new NumberService<Number>();
What if the previous NumberService and StringService are both registered in the Spring container? Spring is also a bit of a dilemma, as it is impossible to determine which instance to use to inject without @Primary
class Processor<T>
0
Property, similar error occurred
Processor<String> processor = new Processor<>(); //Java 7 Version and above
4
This is the same error as normal property injection with multiple optional instances.
Conclusion under 1
If Spring does not provide any concrete type when it initializes a generic class, it initializes the instance with the upper bound type
@Named class Processor<T> -> new Processor<Object>()
@Named class Processor<T extends Number> -> new Processor<Number>();
If the generic type is associated with the specific type of the property being injected, the primary type is inferred from the property type
Processor<String> processor = new Processor<>(); //Java 7 Version and above
5
At this point, the Spring container exists
class StringService implements Service<String>
An instance of the property
service(StringService 实例)
It is inferred that the specific type of Processor is
Processor<String>
Of course, this Processor class can also be defined as a bit more complex 1, such as
Processor<String> processor = new Processor<>(); //Java 7 Version and above
6
About this article's sample code can be reference https: / / github com yabqiu/spring - generic - demo, please run mvn spring - boot: run view the output results to understand how to initialize the Spring generic class instance.
Ok, that's the whole content of this article, I hope the content of this article can help you to learn or use Spring, if you have any questions, you can leave a message to communicate.