@import/@importResource的理解
总括:
@Import
1,引入具有@configure注解的配置类---相当于xml的include
2,引入实现了importSelector,或importBeanDefintionRegister的子类返回的类实例,这种类的顺序前于配置类的顺序---用于初始化前置条件的类
一般在@Enable***注解使用,就是在这个功能的所有配置加载之前,先加载importEslector中的前置配置
例子1:
@Import(feignClientsRegister.class)
punlic @interface EnableFeignClients
feignClientsRegister 中的registerBeanDefinitions就初始化类
例子2:
public static class MyImportSelector implements ImportSelector {
/**
* AnnotationMetadata表示了使用@Import引入MyImportSelector的类的注解meta信息。
* 在这个例子中,annotationMetadata可以获取到Config类上的注解详细信息。
*/
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
/*System.out.println("class name --> " + annotationMetadata.getClass().getSimpleName());
System.out.println("className --> " + annotationMetadata.getClassName());
Set<String> annotationTypes = annotationMetadata.getAnnotationTypes();
System.out.println(annotationTypes);*/
// System.out.println("" + annotationMetadat);
System.out.println("----MyImportSelector-----");
return new String[] {"cn.xtt.study.spring.imports.Main.Config_1"};---------将被引入的实例
}
原文:https://blog.csdn.net/xt8469/article/details/82260091
@ImportResource
直接引入xml方式的配置文件
@PropertySource
属性文件
前言
为什么研究这两个注解,是因为在看Spring Boot源码的时候,对于其中大量的EnableXXX都使用了@Import注解,所以决定研究下这个注解,顺便写了一点关于@ImportRescource注解的东西,希望对大家有帮助。
@Import
简介:功能类似XML配置的,用来导入配置类,可以导入带有@Configuration注解的配置类或实现了ImportSelector/ImportBeanDefinitionRegistrar,或者导入普通的POJO(Spring会将其注册成Spring Bean,导入POJO需要使用Spring 4.2以上)。
下面注解源码,源码有比较详细的英文解释:
/**
* Indicates one or more {@link Configuration @Configuration} classes to import.
*
* <p>Provides functionality equivalent to the {@code <import/>} element in Spring XML.
* Allows for importing {@code @Configuration} classes, {@link ImportSelector} and
* {@link ImportBeanDefinitionRegistrar} implementations, as well as regular component
* classes (as of 4.2; analogous to {@link AnnotationConfigApplicationContext#register}).
*
* <p>{@code @Bean} definitions declared in imported {@code @Configuration} classes should be
* accessed by using {@link org.springframework.beans.factory.annotation.Autowired @Autowired}
* injection. Either the bean itself can be autowired, or the configuration class instance
* declaring the bean can be autowired. The latter approach allows for explicit, IDE-friendly
* navigation between {@code @Configuration} class methods.
*
* <p>May be declared at the class level or as a meta-annotation.
*
* <p>If XML or other non-{@code @Configuration} bean definition resources need to be
* imported, use the {@link ImportResource @ImportResource} annotation instead.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.0
* @see Configuration
* @see ImportSelector
* @see ImportResource
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
* or regular component classes to import.
*/
Class<?>[] value();
}
关于Configuration和POJO,没什么好说的,就是简单的配置。这里说下ImportSelector和ImportBeanDefinitionRegistrar的作用(虽然开发过程中很少会使用到,但是Spring和Spring Boot的源码大面积使用了这个功能)。
ImportSelector
根据AnnotationMetadata(实质上是引入@Import注解的类的注解信息),来判断是否引入哪些配置类,通过字符串数组的方式返回配置类的全限定名。
DeferredImportSelector
ImportSelector的子接口,区别是,他会在所有的@Configuration类加载完成之后再加载返回的配置类。ImportSelector会在当前Configuration类加载之前去加载返回的配置类。
可以使用@Order注解或者Ordered接口来指定DeferredImportSelector的加载顺序。
并且提供了新的方法getImportGroup()用来跨DeferredImportSelector实现自定义Configuration的加载顺序。
ImportBeanDefinitionRegistrar
根据AnnotationMetadata(实质上是引入@Import注解的类的注解信息), 来注册BeanDenfinition,通过BeanDefinitionRegistry实例的register可以注册BeanDefinition。
三个接口的使用例子在文章最后面。
@ImportResource
和@Import类似,区别就是@ImportResource导入的是配置文件。
同样源码如下
/**
* Indicates one or more resources containing bean definitions to import.
*
* <p>Like {@link Import @Import}, this annotation provides functionality similar to
* the {@code <import/>} element in Spring XML. It is typically used when designing
* {@link Configuration @Configuration} classes to be bootstrapped by an
* {@link AnnotationConfigApplicationContext}, but where some XML functionality such
* as namespaces is still necessary.
*
* <p>By default, arguments to the {@link #value} attribute will be processed using a
* {@link org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader GroovyBeanDefinitionReader}
* if ending in {@code ".groovy"}; otherwise, an
* {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader XmlBeanDefinitionReader}
* will be used to parse Spring {@code <beans/>} XML files. Optionally, the {@link #reader}
* attribute may be declared, allowing the user to choose a custom {@link BeanDefinitionReader}
* implementation.
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.0
* @see Configuration
* @see Import
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface ImportResource {
/**
* Alias for {@link #locations}.
* @see #locations
* @see #reader
*/
@AliasFor("locations")
String[] value() default {};
/**
* Resource locations from which to import.
* <p>Supports resource-loading prefixes such as {@code classpath:},
* {@code file:}, etc.
* <p>Consult the Javadoc for {@link #reader} for details on how resources
* will be processed.
* @since 4.2
* @see #value
* @see #reader
*/
@AliasFor("value")
String[] locations() default {};
/**
* {@link BeanDefinitionReader} implementation to use when processing
* resources specified via the {@link #value} attribute.
* <p>By default, the reader will be adapted to the resource path specified:
* {@code ".groovy"} files will be processed with a
* {@link org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader GroovyBeanDefinitionReader};
* whereas, all other resources will be processed with an
* {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader XmlBeanDefinitionReader}.
* @see #value
*/
Class<? extends BeanDefinitionReader> reader() default BeanDefinitionReader.class;
}
default和locations作用相同,都是用来指定配置文件的位置。
关于reader,一般情况下们不需要指定这个属性,默认情况,如果配置文件是.groovy结尾的将会使用GroovyBeanDefinitionReader来进行解析,其他的将会使用XmlBeanDefinitionReader来进行解析。一般需要显示的指定reader的情况是开发者需要实现自己的配置文件方式,比如说自己实现了一个JSONBeanDefinitionReader用来解析JSON的配置文件以达到可以将Spring以JSON的方式进行配置(开发中使用较少)。
一般情下,Spring还是推荐使用@Import而不是@ImportResource。
附页-@Import的测试代码
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Config.class, Config1.class);
context.refresh();
}
public static class BeanDemo0 {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Configuration
@Import({MyImportSelector.class, MyImportBeanDefinitionRegistrar.class, MyImportSelector1.class})
public static class Config {
@Bean
public BeanDemo0 beanDemo() {
System.out.println("----beanDemo----");
BeanDemo0 beanDemo0 = new BeanDemo0();
beanDemo0.setId(1);
beanDemo0.setName("123");
return beanDemo0;
}
}
@Configuration
public static class Config_1 {
@Bean
public BeanDemo0 beanDemo_1() {
System.out.println("----beanDemo_1----");
BeanDemo0 beanDemo0 = new BeanDemo0();
beanDemo0.setId(1);
beanDemo0.setName("123");
return beanDemo0;
}
}
@Configuration
public static class Config0 {
@Bean
public BeanDemo0 beanDemo0() {
System.out.println("----beanDemo0----");
BeanDemo0 beanDemo0 = new BeanDemo0();
beanDemo0.setId(1);
beanDemo0.setName("123");
return beanDemo0;
}
}
@Configuration
public static class Config00 {
@Bean
public BeanDemo0 beanDemo00() {
System.out.println("----beanDemo00----");
BeanDemo0 beanDemo0 = new BeanDemo0();
beanDemo0.setId(1);
beanDemo0.setName("123");
return beanDemo0;
}
}
@Configuration
public static class Config000 {
@Bean
public BeanDemo0 beanDemo000() {
System.out.println("----beanDemo000----");
BeanDemo0 beanDemo0 = new BeanDemo0();
beanDemo0.setId(1);
beanDemo0.setName("123");
return beanDemo0;
}
}
@Configuration
public static class Config0000 {
@Bean
public BeanDemo0 beanDemo0000() {
System.out.println("----beanDemo0000----");
BeanDemo0 beanDemo0 = new BeanDemo0();
beanDemo0.setId(1);
beanDemo0.setName("123");
return beanDemo0;
}
}
@Configuration
@Import({MyImportSelector2.class})
public static class Config1 {
@Bean
public BeanDemo0 beanDemo1() {
System.out.println("----beanDemo1----");
BeanDemo0 beanDemo0 = new BeanDemo0();
beanDemo0.setId(1);
beanDemo0.setName("123");
return beanDemo0;
}
}
@Configuration
public static class Config2 {
@Bean
public BeanDemo0 beanDemo2() {
System.out.println("----beanDemo2----");
BeanDemo0 beanDemo0 = new BeanDemo0();
beanDemo0.setId(1);
beanDemo0.setName("123");
return beanDemo0;
}
}
public static class MyImportSelector implements ImportSelector {
/**
* AnnotationMetadata表示了使用@Import引入MyImportSelector的类的注解meta信息。
* 在这个例子中,annotationMetadata可以获取到Config类上的注解详细信息。
*/
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
/*System.out.println("class name --> " + annotationMetadata.getClass().getSimpleName());
System.out.println("className --> " + annotationMetadata.getClassName());
Set<String> annotationTypes = annotationMetadata.getAnnotationTypes();
System.out.println(annotationTypes);*/
// System.out.println("" + annotationMetadat);
System.out.println("----MyImportSelector-----");
return new String[] {"cn.xtt.study.spring.imports.Main.Config_1"};
}
}
/**
* after all config
*/
public static class MyImportSelector1 implements DeferredImportSelector {
@Override
public Class<? extends Group> getImportGroup() {
return MyGroup.class;
}
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
System.out.println("----DeferredImportSelector1-----");
return new String[]{"cn.xtt.study.spring.imports.Main.Config0", "cn.xtt.study.spring.imports.Main.Config00"};
}
}
public static class MyImportSelector2 implements DeferredImportSelector {
@Override
public Class<? extends Group> getImportGroup() {
return MyGroup.class;
}
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
System.out.println("----DeferredImportSelector2-----");
return new String[]{"cn.xtt.study.spring.imports.Main.Config000", "cn.xtt.study.spring.imports.Main.Config0000"};
}
}
public static class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
System.out.println("----MyImportBeanDefinitionRegistrar----");
/*System.out.println(annotationMetadata);
System.out.println("class name --> " + annotationMetadata.getClass().getSimpleName());
System.out.println("className --> " + annotationMetadata.getClassName());
System.out.println(registry);
System.out.println("registry name " + registry.getClass().getSimpleName());*/
registry.registerBeanDefinition("config2", new RootBeanDefinition(Config2.class));
}
}
private static class MyGroup implements DeferredImportSelector.Group {
private List<Entry> entries = new ArrayList<>(2);
@Override
public void process(AnnotationMetadata metadata, DeferredImportSelector selector) {
for (String configClassName : selector.selectImports(metadata)) {
entries.add(new Entry(metadata, configClassName));
}
entries.sort(new Comparator<Entry>() {
@Override
public int compare(Entry o1, Entry o2) {
//按照配置类,全限定名的长度,从名称长的开始加载
return o2.getImportClassName().length() - o1.getImportClassName().length();
// return o1.getImportClassName().length() - o2.getImportClassName().length();
}
});
}
@Override
public Iterable<Entry> selectImports() {
return entries;
}
}
}
运行结果:
----MyImportSelector-----
----DeferredImportSelector1-----
----DeferredImportSelector2-----
----MyImportBeanDefinitionReistrar----
----beanDemo_1----
----beanDemo----
----beanDemo1----
----beanDemo0000----
----beanDemo000----
----beanDemo00----
----beanDemo0----
----beanDemo2----
原文:https://blog.csdn.net/xt8469/article/details/82260091
相关推荐
<add key="RedisPath" value="127.0.0.1:6379"/> todo:这里配置自己redis的ip地址和端口号。//ReadServerList:可读的Redis链接地