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

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

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

public class NumberService<R extends Number> implements Service<R> {
 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?

public class Processor<T> {
 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 

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 

So in front Processor<T> The instance is equivalent to

Processor<String> processor = new Processor<>(); //Java 7  Version and above 

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 

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 

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 

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.

Related articles: