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配置文件加载过来并且当成一个外部配置类,并执行
比如
标签:springboot,springcloud,class,装载,bean,User,import,注解,public From: https://blog.51cto.com/u_12528551/5900178