When using @Import to register a configuration class in Spring, this configuration class should no longer be annotated with @Component or @Configuration

Three types of @Import annotation parameters

Common bean type

The imported class will be registered as a Bean in the Spring container, which can be used by dependency injection, and beanName is the full class name.

ImportSelector type

The ImportSelector implementation class will not be registered as a Bean of the Spring container, but the full class name returned by its interface method will be registered as a bean, and beanName is the full class name

//MyImportSelector不会被注册为bean
public class MyImportSelector implements ImportSelector {
    
    

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
    
    
        //ImportedBean1被注册为bean,并且beanName为全类名
        return new String[]{
    
    ImportedBean1.class.getName()};
    }
}

ImportBeanDefinitionRegistrar type

The ImportBeanDefinitionRegistrar implementation class will not be registered as a bean, but its interface method will be called back, and the developer will manually register the bean with the Spring container through the Spring api

public MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
    

	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
    
    
	   //可以通过registry向Spring容器注册bean
	}
}

When @Import registers a configuration class, this configuration class should not be marked with @Component or @Configuration annotations.

Spring will encapsulate all bean classes into one ConfigurationClass, and then parse these configuration classes. There will be a boolean type return value method in this class boolean ConfigurationClass#isImportedto determine whether the encapsulated bean class is imported by other classes. The method notes are as follows:

Return whether this configuration class was registered via @Import 
or automatically registered due to being nested within another configuration class.

Chinese explanation: If it is a class registered through @Import or an internal class defined in the configuration class, it will return true, and it is understood whether it is imported by other classes.
The following example:

//其他代码省略....
@Import(B.class)
@ConditionOnBean(C.class) //条件验证bean C是否存在
class A{
    
    
   //只有当A上的条件验证通过时才会向Spring容器注入D
   @Bean
   public D d(){
    
    
       return new D();
   }
}

In the example, B is a Bean imported by A

When the imported class B is being instantiated, Spring will first verify whether the conditional annotation on the imported class A of B is verified, and if it passes, then B will be instantiated. The results of conditional verification annotations will be cached at the same time.

And @Componentor @Configurationannotation will @Import Class B is introduced, to be scanned during scanning Spring package is executed, at this time would not be considered a class A introduced. If Bean B is instantiated at this time, but B depends on the bean D defined in A, but the condition verification of A at this time is not passed, it will cause bean B to be unable to rely on bean D when it is created, and an exception will be thrown at the end.

If class B is normally imported by class A without being @Componentor @Configurationannotated, then before bean B is instantiated, it will first verify whether the conditional annotation on class A passes. If it passes, then class B depends on the definition in A during the instantiation process The bean D can also be created normally, and all the dependencies of B are injected. If it fails, bean B will not be created, and bean D defined in A will not be searched from the Spring container, and the application will execute normally.

Guess you like

Origin blog.csdn.net/u013202238/article/details/107126622