Spring中使用@Import注册一个配置类时,这个配置类不应该再使用@Component或者@Configuration注解

@Import注解参数三种类型

普通Bean类型

被导入的类会被注册成Spring容器中的一个Bean,可以被依赖注入使用,beanName为全类名。

ImportSelector类型

ImportSelector实现类不会被注册为Spring容器的一个Bean,但是其接口方法返回的全类名会被注册成bean,并且beanName为全类名

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

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

ImportBeanDefinitionRegistrar类型

ImportBeanDefinitionRegistrar实现类不会被注册为bean,但是会回调其接口方法,由开发者通过Spring api手动向Spring容器注册bean

public MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
    

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

@Import注册一个配置类时,这个配置类不应该被@Component或者@Configuration注解标记。

Spring中会将所有的bean class封装成一个ConfigurationClass,并且此后会解析这些配置类,该类中会有一个boolean类型返回值方法boolean ConfigurationClass#isImported,用于判断被封装的bean class是否是由其他类导入的。方法注释如下:

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

中文解释:如果是通过@Import注册的类或者在配置类中定义的内部类会返回true,这里理解是否由其他类导入的。
如下示例:

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

示例中B就是由A导入的一个Bean

当被导入的类B在被实例化时,Spring会先验证导入B的A类上的条件注解是否验证通过,如果通过才会实例化B。而条件验证注解的结果同时会被缓存。

@Component或者@Configuration注解会让被@Import导入的类B,在Spring执行包扫描时被扫描到,此时不会被认为是由类A导入的。假如此时实例化Bean B,但是B依赖了A中定义的bean D,但是A此时的条件验证是不通过的,则会导致bean B创建时无法依赖bean D,最后抛出异常。

如果类B正常由类A导入,没有被@Component或者@Configuration注解,那么在bean B实例化之前,会先验证类A上的条件注解是否通过,如果通过,那么类B在实例化过程中所依赖A中定义的bean D时也能够正常被创建,并被B所有依赖注入。如果不通过,则不会创建bean B,此时也不会查找从Spring容器中查找A中所定义的bean D,应用正常执行.

猜你喜欢

转载自blog.csdn.net/u013202238/article/details/107126622