Spring Boot基础(二)自动配置:Import注解

Enbale的基本:Import注解

@Enbale底层依赖于@Import注解导入一些类,使用Import导入的类会被Spring加载到IoC容器中,而@Import提供了4中用法:

  • 导入Bean:直接导入实体类
  • 导入配置类:导入配置类中定义的所有Bean
  • 导入ImportSelect实现类,用于加载配置文件中的类
  • 导入ImportBeanDefinitionRegistrar实现类

 

直接导入Bean

复制代码
@SpringBootApplication
@Import(User.class)   //导入实体类
public class SprintbootMyUnApplication {

    public static void main(String[] args) {
        //启动SpringBoot,获取Ioc
        ConfigurableApplicationContext context = SpringApplication.run(SprintbootMyUnApplication.class, args);
     //直接根据实体类的class获取bean
        User bean = context.getBean(User.class);
     //获得的是一个map,从map中可以查看Bean的名称,一般是类的全限定名 Map
<String, User> beans = context.getBeansOfType(User.class);
System.out.println(bean); System.out.println(beans); }
复制代码

 

导入配置类

复制代码
@SpringBootApplication
//UserConfig中定义的所有类,都会被创建
@Import(UserConfig.class)
//@EnableUser
//@Import(User.class)
public class SprintbootMyUnApplication {

    public static void main(String[] args) {
        //启动SpringBoot,获取Ioc
        ConfigurableApplicationContext context = SpringApplication.run(SprintbootMyUnApplication.class, args);
      Object user = context.getBean("user153"); Object role = context.getBean("role"); System.out.println(user); System.out.println(role); }
复制代码

配置类(注意包名要对上):

复制代码
@Configuration //当使用Import注解导入这个配置类时,这个注解可加可不加
public class UserConfig {

    @Bean
    public User user153(){
        return new User();
    }
    @Bean
    public Role role(){
        return new Role();
    }
}
复制代码

 

导入ImportSelect实现类

Spring Boot官方就是用的这种方式,路径:@SpringBootApplication——>@EnableAutoConfiguration——>@Import(AutoConfigurationImportSelector.class)——>AutoConfigurationImportSelector。

AutoConfigurationImportSelector实现了DeferredImportSelector接口,而DeferredImportSelector实现了ImportSelector接口。后面会详细介绍这个实现类

 

复制代码
@SpringBootApplication
//imports实现了ImportSelect接口的实现类,也可以导入Bean
@Import(MyImportSelector.class)
public class SprintbootMyUnApplication {

    public static void main(String[] args) {
        //启动SpringBoot,获取Ioc
        ConfigurableApplicationContext context = SpringApplication.run(SprintbootMyUnApplication.class, args);

        Object user = context.getBean(User.class);
        Object role = context.getBean(Role.class);
        System.out.println(user);
        System.out.println(role);
    }
复制代码

实现类:

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
     //这里的字符串可以动态替换
return new String[]{"com.yz.domin.Role","com.yz.domin.User"}; } }

 

导入ImportBeanDefinitionRegistrar实现类

复制代码
@SpringBootApplication
//@ComponentScan("com.yz.config")
//@Import(UserConfig.class)
//@EnableUser
//@Import(User.class)
//@Import(MyImportSelector.class)
@Import(MyImportBeanDefinitionRegistrar.class)
public class SprintbootMyUnApplication {

    public static void main(String[] args) {
        //启动SpringBoot,获取Ioc
        ConfigurableApplicationContext context = SpringApplication.run(SprintbootMyUnApplication.class, args);
     //导入User,因为Role没有被创建
        Object user = context.getBean("user88");
        //Object role = context.getBean(Role.class);
        System.out.println(user);
        //System.out.println(role);
    }
复制代码

实现类:

复制代码
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //手动向Ioc容器里注入Bean
        //定义bean的类型
        AbstractBeanDefinition definition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
        //定义bean的名字
        registry.registerBeanDefinition("user88", definition);
    }
}
复制代码

 

 

 EnableAutoConfiguration注解

@EnableAutoConfiguration注解内部使用@Import(AutoConfigurationImportSelector.class) 来加载配置类,这个AutoConfigurationImportSelector就是基于ImportSelector实现的

在源码中对应路径:

@SpringBootApplication——>@EnableAutoConfiguration——>@Import(AutoConfigurationImportSelector.class)——>AutoConfigurationImportSelector类——>getCandidateConfigurations()。

在这个方法中,使用SpringFactoriesLoader.loadFactoryNames()方法获取到一个字符串集合,这些就是被加载出来的bean,来源就是META-INF/spring.factories配置文件,该文件中定义了大量配置类当SpringBoot应用启动时,会自动加载这些配置类,并初始化bean。如果configurations 集合为空,在META-INF/spring.factories文件里找不到自动配置类,就会报出异常

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
                getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
                + "are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

 

这个META-INF/spring.factories的文件就在springboot自动配置的包里:org.sprintbootframework.boot:spring-boot-autoconfigure:version

 

 

 

 spring.factories文件

这里所有的Configraution都是会被加载的(多数都会有ConditionalOnXXX条件注解来按条件创建

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
………………

 

posted @   我永远喜欢石原里美  阅读(504)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示

目录导航