SpringBoot--自动装配之Import注解以及源码分析

SpringBoot--自动装配之Import注解以及源码分析,第1张

SpringBoot--自动装配之Import注解以及源码分析

        上期我们讲解SpringBoot中使用的Conditional注解以及在自动装配中是如何使用的,这期我们来讲一讲,SpringBoot中的import注解、官方是如何使用的以及自动装配的源码解析。

一、import注解

我们先来看一下这个注解的作用:使用@import导入的类都会被加载到ioc容器中

@import的4种用法

  1. 导入Bean
  2. 导入配置类
  3. 导入importSelector实现类,一般用于加载配置文件中的类
  4. 导入importBeanDefinitionRegistrar实现类 

下面我们来逐一演示

一、导入Bean、导入配置类(这两个很简单就放到一起演示了)

新建一个类叫User

public class User {
}

再建一个User的配置类UserConfig

public class UserConfig {
    @Bean
    public User getUser(){
        return new User();
    }
}

然后我们在引导类中添加一个@import,导入我们刚刚写的UserConfig

@import(UserConfig.class)
@SpringBootApplication
public class SpringbootApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootApplication.class, args);
        // 根据类型获取相对应的对象
        User bean = context.getBean(User.class);
        System.out.println(bean);

    }
}

这时候启动项目就发现控制台输出了该对象

这时候可能就有人好奇了, import中明明写的UserConfig, 我们却只获取了User,能不能获取UserConfig这个对象, 结果是可以的 

@import(UserConfig.class)
@SpringBootApplication
public class SpringbootApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootApplication.class, args);
        // 根据类型获取相对应的对象
        User bean = context.getBean(User.class);
        UserConfig bean1 = context.getBean(UserConfig.class);

        System.out.println(bean);
        System.out.println(bean1);
    }
}

 两者都能输出,并且能看到他们的路径, 这是因为被导入的UserConfig里面的方法将User放入了Ioc

所以当我们只用@import导入User.class时,是会显示报错信息的

意思是在容器中没有找到com.zhm.springboot.UserConfig类型的实例 

 导入UserConfig本质上就是导入配置类, 只是这个类上的@Configuration可以省略

二、导入importSelector实现类

我们先来看一下这个接口

定义了一个方法反悔了一个String[], 然后传参是注解元数据

那我们也定义一个类MyimportSelector来实现它,里面放入两个我们自定义的类的路径

public class MyimportSelector implements importSelector {
    @Override
    public String[] selectimports(Annotationmetadata annotationmetadata) {
        return new String[]{"com.zhm.springboot.domain.User","com.zhm.springboot.domain.Student"};
    }
}
@import(MyimportSelector.class)
@SpringBootApplication
public class SpringbootApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootApplication.class, args);

        System.out.println(context.getBean(Student.class));
        System.out.println(context.getBean(User.class));
    }
}

 启动项目也是成功的打印了

 三、导入importBeanDefinitionRegistrar实现类 

最后一种用法,我们先来看下这个接口

 我们也自定义一个类来实现它

public class MyimportBeanDefinitionRegistrar implements importBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) {

        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(User.class);
        
        AbstractBeanDefinition definition = beanDefinitionBuilder.getBeanDefinition();
        
        registry.registerBeanDefinition("user",definition);
    }
}

引导类中我们进行这样的修改

@import({MyimportBeanDefinitionRegistrar.class})
@SpringBootApplication
public class SpringbootApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootApplication.class, args);

        System.out.println(context.getBean(User.class));

        System.out.println(context.getBean("user"));
    }
}

看下启动项目的打印结果

 

 这样写的好处就是可以自定义ioc中的bean的名称

二、SpringBoot的中使用

介绍完@import之后, 开始今天的重点, 跟踪一下springboot中自动装配的源码

@SpringBootApplication
public class SpringbootApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }
}

一切的源头都要从springboot 中的引导类开始说起

引导类中有两个重要的点

  1. run方法(加载流程)
  2. @SpringBootApplication (开启自动装配,包扫描,配置类)

第一点我们先不讲, 重点在@SpringbootApplication身上,我们点进去这个注解

被框出来的注解@EnableAutoConfiguration就是开启自动装配(其他的注解暂时先不介绍),我们继续点进去

 被红框框中的就是我们上面一直在介绍的@import, 可以很明显的看到使用的是第三种方法,导入importSelector的实现类,我们点进这个实现类继续看

可以看到它跟我们一样, 重写了selectimports这个方法, 返回的结果是一个String[], 有印象的朋友可能还记得我们@import注解就是存的一个String[],我们点进红框中的方法继续看

 

 红框中的方法返回就是一个类型为String的list,于是我们继续点进去

 

可以清晰的看到这边有一个断言, 写的就是 在meta-INF/spring.factories中没有找到一条配置, 那也就是说我们的自动装配都放在了 meta-INF/spring.factories中, 我们点进上面的loadFactoryNames方法

图中FACTORIES_RESOURCE_LOCATION常量的值正是

 我们可以打下断点看下启动看下

 

 图中可以看到总共获取了127条需要自动装配的信息, 那么这些路径从哪来的呢, 上一节讲到过了,就在autoconfigure中的路径

同理可得, 如果我们需要在自己的项目中需要自动装配一些配置, 我们只需要在本项目新建路径meta-INF/spring.factories,并在文件中按照这样的写法就可以了

 

 以上就是@import的运用以及springboot自动装配的流程

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5686945.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存