Spring extension point 3: @Import annotation

The role of @Import annotation

Speaking of @Import annotation, what must be said is that
in the implementation methods corresponding to the ImportSelector interface of the following two classes , an array needs to be returned. In the array, the full class name corresponding to the class to be injected into the spring container is
the implementation of the ImportBeanDefinitionRegistrar interface. In the method, the BeanDefinitionRegistry object will be provided, and we can inject a beanDefinition object into the beanDefinitionMap through the object in the method.
This is the function of these two classes.

In the spring source code, the @Import annotation is the most used, which is not an exaggeration. In fact, in most frameworks, you will see that each framework customizes a lot of annotations. Most of these annotations are used @Import annotation is completed, and, through @Import annotation, injected, usually ImportSelector or ImportBeanDefinitionRegistrar implementation class
About the principle of these two extension points, in the previous blog spring source code: @Import annotation
, there is a record Yes, so I won’t give too much explanation, let’s summarize it roughly.

1. In the spring source code, to convert a class object into a bean object that can be received by a spring container, first convert the class object to a beanDefinition object. In the conversion process, the scanning and conversion are usually completed through the @ComponentScan annotation of
2, but a point to consider: there may be ImportSelector we inject the bean implementation class or ImportBeanDefinitionRegistrar, while ImportSelector the injected class, it is possible there ImportSelector or ImportBeanDefinitionRegistrar implementation class, so, in the source code, A recursive judgment will be made, until the current bean is an ordinary bean, and then all the beans are stored in a collection
3. It should be noted that at this time, the ImportSelector and ImportBeanDefinitionRegistrar implementation classes introduced by @Import , The returned bean is still an ordinary class object, and has not been converted to beanDefinition. After the analysis is completed, spring will process these two implementation classes in a unified manner.

4. The so-called unified processing is based on whether the current importBeanDefinitionRegistrar or ImportSelector or @Bean injection is processed, converted to beanDefinition, and then stored in beanDefinitionMap

application

Next, I mainly talk about applications. In fact, for @Import annotations,
1. We can directly introduce an ordinary bean through @Import
2. You can also introduce an implementation class of ImportSelector
3. You can also introduce an implementation class of ImportBeanDefinitionRegistrar

ImportBeanDefinitionRegister

@Configuration
@ComponentScan("com.spring.study.importbeandefinitionregistrar")
@Import({
    
    MyImportBeanDefinitionRegistrar.class,ImportTestBean.class})
public class ImportConfig {
    
    
}
public class ImportTestBean {
    
    
}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
    

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    
    
        System.out.println("自己手动注入一个bean");
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(OrderBean.class);
        registry.registerBeanDefinition("orderBean", beanDefinitionBuilder.getBeanDefinition());
    }
}
public class OrderBean {
    
    
}
public class TestImportBeanDefinitionRegistrar {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ImportConfig.class);
        System.out.println(ac.getBean(OrderBean.class));
        System.out.println(ac.getBean(ImportTestBean.class));
    }
}

The final print result

自己手动注入一个bean
18:49:04.903 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
18:49:04.906 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
18:49:04.907 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
18:49:04.909 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
18:49:04.927 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'importConfig'
18:49:04.936 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.spring.study.importbeandefinitionregistrar.ImportTestBean'
18:49:04.936 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderBean'
com.spring.study.importbeandefinitionregistrar.OrderBean@43301423
com.spring.study.importbeandefinitionregistrar.ImportTestBean@2f112965

The @Import annotation here injects two classes, one is a normal bean, and the other is an implementation class of importBeanDefinitionRegistrar.
Therefore, the role of the ImportBeanDefinitionRegistrar interface is to give the BeanDefinitionRegistry to the programmer, and the programmer himself decides the business logic to be done.

ImportSelector

public class MyImportSelector implements ImportSelector {
    
    

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
    
    
        return new String[]{
    
    "com.spring.study.importselector.OperChannelEntity","com.spring.study.importselector.UserBean"};
    }
}

ImportSelector will not post too much code, as long as this bean is imported through the @Import annotation, spring will help us inject the two classes of OperChannelEntiry and UserBean

The automatic injection of springboot uses this point to implement ImportSelector, and then obtain the full class name of the bean to be automatically injected, and then put it into the returned array.

Guess you like

Origin blog.csdn.net/CPLASF_/article/details/115207928