@Import注解使用详解
SPRING容器注解@Import
最近在研究springboot源码和spring secruity过滤链,发现一个注解很常用@Import,研究了一下发现功能起始和@Bean一样在IOC容器注入对象,但是好像牛皮多了一点,就整理了一下学习资料.
Import的作用
基本上作用就是通过不同方式将bean对象放到你的IOC容器中.这里的IOC容器可以使用Spring的AnnotationConfigApplicationContext直接加载一个入口测试类,也可以通过springboot的启动类做测试,这里我们选择后者.
第一种方式,直接导入class
先来一个类TestBean1
package cn.tedu.normal;
public class TestBean1 {
public TestBean1(){
System.out.println("哎,我TestBean1被谁创建了怎么回事");
}
}
在springboot启动类中(本身这就是一个spring容器入口类),添加类注解@Import将TestBean1创建导入到容器中.
package cn.tedu;
import cn.tedu.normal.TestBean1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
@SpringBootApplication
@Import({TestBean1.class})
public class SpringImportAnnotaionDemo01Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringImportAnnotaionDemo01Application.class, args);
}
}
然后启动,可以看到有什么效果,在控制台可以打印bean被加载了这一句话,当然也可以到各种其他代码中注入这个bean使用了.所以你可能知道一万中把bean对象加载到IOC中,import是其中一种.
看见了吗,对象通过import确实被加载了,可以通过@Autowired测试是否在IOC容器.
第二种方式,导入选择器
在这里说这种方式能干什么你还理解不了,所以先做.导入选择器,必须让我们的选择器类实现一个接口ImportSelector.
咱们先准备一个测试类TestBean2.
package cn.tedu.normal;
public class TestBean2 {
public TestBean2(){
System.out.println("哎,我TestBean2也被加载了");
}
}
一个普通的class,即将被我们使用导入选择器的方式导入到当前容器IOC中.
实现一个ImportSelector接口的类.
package cn.tedu.selector;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
String[] classes={"cn.tedu.normal.TestBean2"};
return classes;
}
}
需要实现一个接口方法selectImports,还有个参数annotationMetadata,这个参数中保存了使用该importSelector对象所在的配置类的注解信息.如果我们是在一个spring boot启动类中使用了@SpringBootApplication和@Import导入的话,这个参数中就会保存这2个注解可以给我们使用.作用是什么目前还没整明白,不过这个参数在这里不重要.
看到代码里我们在实现方法中返回了一个数组,数组元素值就是我们想要让容器通过这个ImportSelector导入时创建的类的全路径名称.看到这里你就可以去翻一翻springboot的源码了aaa@qq.com就是通过导入一个选择器实现各种底层自定义配置类的加载的.
package cn.tedu;
import cn.tedu.normal.TestBean1;
import cn.tedu.selector.MyImportSelector;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
@SpringBootApplication
@Import({TestBean1.class, MyImportSelector.class})
public class SpringImportAnnotaionDemo01Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringImportAnnotaionDemo01Application.class, args);
}
}
启动容器,发现两个bean都被加载了.
第三种方式,导入BeanDefinitionRegistrar
上述两种方式导入的bean对象总结一下,Import导入class,你得一个类一个类的挑出来放到注解属性值中,而ImportSelector导入就方便了,只要准备好一个文件里面记录所有导入的类全路径名称就搞定.两种方式都是默认使用类路径名称来做对象的id.还有第三种导入的内容,我们可以导入一个自定义id等参数的bean对象
准备一个测试类TestBean3
package cn.tedu.normal;
public class TestBean3 {
public TestBean3(){
System.out.println("哎,TestBean3被加载了");
}
}
准备一个ImportBeanDefinitionRegistrar实现类
package cn.tedu.registrar;
import cn.tedu.normal.TestBean3;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
BeanDefinition beanDefinition=new RootBeanDefinition(TestBean3.class);
System.out.println("定义bean的各种属性"+beanDefinition.getBeanClassName()+"/"+beanDefinition.getDescription()+"/"
+beanDefinition.getParentName()+"/"+beanDefinition.getScope());
beanDefinitionRegistry.registerBeanDefinition("haha",beanDefinition);
}
}
这里又在干什么呢.beanDefinition定义的是通过这种方式创建容器bean时,对于bean的一些参数属性,在测试代码中我将RootBeanDefinition中的一些默认值打印了出来,然后自定义haha作为bean的名称来使用.
在springboot启动类中添加自定义registrar类
package cn.tedu;
import cn.tedu.normal.TestBean1;
import cn.tedu.registrar.MyImportRegistrar;
import cn.tedu.selector.MyImportSelector;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
@SpringBootApplication
@Import({TestBean1.class, MyImportSelector.class, MyImportRegistrar.class})
public class SpringImportAnnotaionDemo01Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringImportAnnotaionDemo01Application.class, args);
}
}
最后启动可以看到输出结果
hong
红框上的就是beanDefinitin中的默认各种值.这里没有继续修改,还可以获取其他值.
上一篇: Leetcode17 电话号码的字母组合
下一篇: tensorflow入门变量常量