Spring 注册组件的几种方式


共计 2500 个字符,预计需要花费 7 分钟才能阅读完成。

向 Spring 容器中注册组件是最常见的操作,不过组件注册的方式有很多种,可以选择合适的方式进行注册。

1. @ComponentScan注解

这种方式会将指定包下配置了 @Component@Controller@Service@Repository 的组件注册到容器中。

另外 @ComponentScan 注册组件可以指定和排除某些类或者用注解标记的某些类。

例如:

// 这里的 @Configuration 注解其实也是一个 @Component
@Configuration
@ComponentScan(
        value = {"com.amjun.annotation.register.register_01"},
        excludeFilters = {
            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes= MyService.class)
        }
)
public class Config {}

这种方式一般用于将自己编写的代码进行注册,因为第三方的代码可能不包含这些注解。

2. @Bean注解

@Bean 注解是一个常见的注解,它等价于 xml 配置文件中的 标,大部分用于将第三方的类注册到 spring 容器中。

例如:

@Configuration
public class Config {

    @Lazy
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @Bean
    public Person person(){
        return new Person("zs", 18);
    }
}

还可以可以通过 @Scope 配置注册到容器是单例还是多例,通过 @Lazy 控制是否懒加载创建。(spring 默认是直接初始化放入容器中,使用该注解后需要时再创建)

3. @Import注解

@Import 允许将一个或多个类注册到 Spring 容器中,这些类会被作为 Bean 进行管理。关于它的使用,有以下几种方式。

  • 导入普通类

该普通类可以是什么都没有标注的类,也可以是自己或第三方标注了 @Configuration 的配置类。

@Configuration
@Import(Person.class)
public class Config {
}

或者:

@Configuration
@Import(TestImportConfig.class)
public class Config {
}

@Configuration
public class TestImportConfig {

    @Bean
    public Person person(){
        return new Person("zs", 18);
    }
}
  • 使用 ImportSelector 动态选择类

ImportSelector 是一个接口,允许根据条件动态选择导入的类。

@Configuration
@Import(MyImportSelector.class)
public class Config_02 {
}

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.amjun.annotation.register.register_03.Person"};
    }
}

selectImports 方法返回的类名会被动态加载到应用上下文中,它的返回是一个数组,意味着可以批量注册。

  • 使用 ImportBeanDefinitionRegistrar

ImportBeanDefinitionRegistrar 是一个接口,通过实现 registerBeanDefinitions 接口,拿到 BeanDefinitionRegistry 进行手动注册

所有需要注册到 spring 容器中的组件,扫描后会组装成一个个 BeanDefinition,并注册到BeanDefinitionRegistry 中,再进行初始化。

@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class Config_03 {
}

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition(Person.class);
        registry.registerBeanDefinition("person", beanDefinition);
    }
}

4. FactoryBean接口

FactoryBean 是 spring 提供的特殊接口,实现了 FactoryBean 接口的类,从 spring 容器中获取时,不是返回对象本身,而是 getObject() 方法返回的对象。这就提供了一种扩展的可能,可以在这个方法里定制创建复杂的逻辑。

@Configuration
public class Config {

    @Bean
    public PersonFactoryBean person(){
        return new PersonFactoryBean();
    }
}

public class PersonFactoryBean implements FactoryBean<Person> {

    @Override
    public Person getObject() throws Exception {
        return new Person("lisi", 100);
    }

    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }
}

Tips:清朝云网络工作室

阅读剩余
THE END