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#isImported
to 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 @Component
or @Configuration
annotation 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 @Component
or @Configuration
annotated, 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.