springcloud之springboot自动装载

       

ImportSelector接口是Spring导入外部配置的核心接口,在SpringBoot的自动配置和@EnableXXX(功能性注解)中起到了决定性的作用.当在@Configuration标注的Class上使用@Import引入了一个ImportSelector实现类后,会把实现类中返回的Class名称都定义为bean. 

使用ImportSelector的例子:

1-定义Bean对象

package cn.itcast.bean;

import lombok.Data;

/**
 * 自定义bean对象
 */
@Data
public class User {
    private String username;
    private Integer age;
}

2-定义配置类Configuration

package cn.itcast.bean;

import org.springframework.context.annotation.Bean;

/**
 * 注意这里没有使用spring的注解,spring启动的时候@Bean不会生效,spring扫描的时候并不会装载该类
 */
public class UserConfiguration {

    @Bean
    public User getUser(){
        User user = new User();
        user.setAge(12);
        user.setUsername("新年快乐");
        return user;
    }
}

3-定义ImportSelector

package cn.itcast.bean;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class UserImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //获取配置类的名称,将UserConfiguration类加入到容器里面,进而@Bean生效,帮助我们创建出User对象
        return new String[]{UserConfiguration.class.getName()};
    }
}

 4-定义@EnableXX注解

package cn.itcast.bean;

import org.springframework.context.annotation.Import;
import java.lang.annotation.*;

/**java元注解
 * @Target :用于描述注解的使用范围,也就是说使用了@Target去定义一个注解,那么可以决定定义好的注解能用在什么地方
 *  *    内部值:ElementType[]  value()数组, value值类型   ElementType枚举类型
 *  *    元注解中的枚举值决定了,一个注解可以标记的范围
 *  *      TYPE : 类型上面  用于描述类、接口(包括注解类型) 或enum声明
 *  *      FIELD : 用于描述字段
 *  *      METHOD :方法
 *  *      PARAMETER : 参数 【参数名】
 *  *      CONSTRUCTOR : 构造方法
 *  *      LOCAL_VARIABLE : 局部变量
 *  *      ANNOTATION_TYPE : 可以打在注解上面
 *  *      PACKAGE :可以打在包上面
 *  *      TYPE_PARAMETER : 参数类型【形式参数类型】
 *  *      TYPE_USE : 任何位置都可以
 *  @Retention:用于描述一个注解存在的生命周期【源码,字节码文件,运行时】
 *  * 	    内部值:RetentionPolicy value();非数组,意味着只能一个值:
 *  * 	    值类型:枚举值RetentionPolicy:几个值决定了几个状态:如下几个值
 *  * 		SOURCE :表示一个注解可以存在于源码中==>java的源码中
 *  *      CLASS :表示 一个注解可以在源码中,并且可以在字节码文件中
 *  *      RUNTIME :表示 一个注解可以在源码、字节码、及运行时期该注解都会存在
 *  @Document :表示该注解是否可以生成到 API文档中 ==》即生成API文档的时 检验
 *  --------------------------------------------------------------------------------------------------------
 *  @Import用来
 *  导入@Configuration注解的配置类,
 *  声明@Bean注解的bean方法,
 *  导入ImportSelector的实现类,
 *  导入ImportBeanDefinitionRegistrar的实现类。
 */
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@Import(UserImportSelector.class)
/**
 * 作用:
 * 这个注解可以配置到一个类上面,自动的找到ImportSelector,找到selectImports方法并执行,
 * 从而加载UserConfiguration,最终在里面得到一个Bean对象
 */
public @interface EnableUserBean {
}

5-测试  test->java->cn.itcast.test.TestApplication

package cn.itcast.test;

import cn.itcast.bean.EnableUserBean;
import cn.itcast.bean.User;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * 执行流程:
 * 根据配置类TestApplication来进行创建容器,会找到注解@EnableUserBean,
 * 借助@Import引入自动装载的ImportSelector选择器,
 * 由UserImportSelector中的selectImports方法说明了spring自动加载的外部配置类的名称,
 * 自动加载UserConfiguration,找到@Bean,得到一个User对象并放到容器里,就可以从容器中获取并得到这个对象
 */
@EnableUserBean
public class TestApplication {
    public static void main(String[] args) {
        //获取spring容器,根据哪个类来加载解析spring容器
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestApplication.class);
        User bean = ac.getBean(User.class);
        System.out.println(bean);
    }
}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

进入ProductApplication的@SpringBootApplication

再进入

public @interface SpringBootApplication中的@EnableAutoConfiguration注解

会发现,

public @interface EnableAutoConfiguration {注解中有
@Import({AutoConfigurationImportSelector.class})

进入AutoConfigurationImportSelector类中,看到了selectImports方法,大量的加载外部的所有配置

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

进入

getAutoConfigurationEntry方法

再进入

getCandidateConfigurations方法

再进入

loadFactoryNames方法

会去扫描自定义的配置和每一个jar包下的spring.factories配置文件加载过来并且当成一个外部配置类,并执行

比如

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值