
在平时看源码或者很多配置类上面都会出现@import注解,功能就是和Spring XML 里面 的 一样. @import注解是用来导入配置类或者一些需要前置加载的类.,springboot框架实现自动装配的原理之一正是利用这一特性解决了spring框架中重量级的xml配置
@import注解源码以及源码描述的翻译
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface import {
Class>[] value();
通过源码的描述翻译可以总结出@import可以通过以下四种方式导入一个bean(其实只有三种):
- 导入普通类(4.2 版本之前只可以导入配置类,4.2版本之后 也可以导入 普通类)
- 导入@Configuration配置类(@Configuration配置类已经是被注册为bean了,因此再用import导入没什么意义
- 导入importSelector实现类
- 导入importBeanDefinitionRegistrar实现类
配置类importConfig
package com.eureka.config;
import com.eureka.register.SelfimportBeanDefinitionRegistrar;
import com.eureka.selector.SelfimportSelector;
import com.eureka.service.TestA;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;
@Configuration
@import({TestA.class})
public class importConfig {
}
普通类TestA
public class TestA {
public void printName() {
System.out.println("我是一个注入的测试类A, " + TestA.class.getName());
}
}
测试:
@SpringBootTest
public class ImprotTest {
@Autowired
private TestA testA;
@Test
public void test() {
testA.printName();
}
}
测试结果:
importSelector实现类如何导入bean,我们来分析下importSelector的源码
public interface importSelector {
String[] selectimports(Annotationmetadata importingClassmetadata);
@Nullable
default Predicate getExclusionFilter() {
return null;
}
}
通过importSelector 源码的描述翻译可以得知importSelector 类的通过 selectimports方法返回的一个类全名的数组,spring容器根据这些类全名查找这些类并注册为bean;如果需要还可以通过getExclusionFilter方法过滤 selectimports返回的不需要注册为bean的类全名
下面分别创建TestB和TestC以及importSelector实现类:
public class TestB {
public void printInfo() {
System.out.println("我是一个注入的测试类B, " + TestA.class.getName());
}
}
public class TestC {
public void printInfo() {
System.out.println("我是一个注入的测试类C, " + TestC.class.getName());
}
}
public class SelfimportSelector implements importSelector {
@Override
public String[] selectimports(Annotationmetadata annotationmetadata) {
return new String[]{"com.eureka.service.TestC","com.eureka.service.TestB"};
}
}
@Configuration
@import({SelfimportSelector.class})
public class importConfig {
}
测试:
@SpringBootTest
public class ImprotTest {
@Autowired
private TestB testB;
@Autowired
private TestC testC;
@Test
public void test1() {
testB.printInfo();
testC.printInfo();
}
}
测试结果:
importBeanDefinitionRegistrar实现类如何导入bean,我们来分析importBeanDefinitionRegistrar的源码
public interface importBeanDefinitionRegistrar {
default void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
registerBeanDefinitions(importingClassmetadata, registry);
}
default void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) {
}
}
根据源码可知 registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) 方法的参数BeanDefinitionRegistry 来注册一个bean对象,我们可以通过将需要注册为bean的类封装成一个BeanDefinition对象交由BeanDefinitionRegistry对象来处理,同时还可以为该类配置相应的属性,此 *** 作相当于spring xml中的bean标签内的所有配置
下面分别创建 DefaultTestService类 和 importTestService类 以及 importBeanDefinitionRegistrar 实现类 SelfimportBeanDefinitionRegistrar
public interface TestService {
void printInfo();
}
public class DefaultTestService implements TestService {
private String beanName;
private String beanType;
private Integer beanTime;
@Override
public void printInfo() {
System.out.println("我是一个注入的default测试类, " + DefaultTestService.class.getName());
}
...getter setter略...
@Override
public String toString() {
return "DefaultTestService{" +
"beanName='" + beanName + ''' +
", beanType='" + beanType + ''' +
", beanTime=" + beanTime +
'}';
}
}
public class importTestService implements TestService {
private String importName;
private String importType;
private String importTime;
@Override
public void printInfo() {
System.out.println("我是一个注入的import测试类, " + importTestService.class.getName());
}
...getter setter略...
@Override
public String toString() {
return "importTestService{" +
"importName='" + importName + ''' +
", importType='" + importType + ''' +
", importTime='" + importTime + ''' +
'}';
}
}
public class SelfimportBeanDefinitionRegistrar implements importBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) {
// 创建DefaultTestService类的BeanDefinition对象
RootBeanDefinition root = new RootBeanDefinition(DefaultTestService.class);
MutablePropertyValues mpv = root.getPropertyValues();
// 给DefaultTestService类设置属性
mpv.addPropertyValue("beanName", "defaultTestService");
mpv.addPropertyValue("beanType", DefaultTestService.class.getTypeName());
mpv.addPropertyValue("beanTime", (int)(Math.random()*1000 + 200));
// 创建importTestService类的BeanDefinition对象
RootBeanDefinition root1 = new RootBeanDefinition(importTestService.class);
MutablePropertyValues mpv1 = root1.getPropertyValues();
// 给importTestService类设置属性
mpv1.addPropertyValue("importName", "importTestService");
mpv1.addPropertyValue("importType", importTestService.class.getTypeName());
mpv1.addPropertyValue("importTime", (int)(Math.random()*1000 + 200));
registry.registerBeanDefinition("defaultTestService", root);
registry.registerBeanDefinition("importTestService", root1);
}
}
@Configuration
@import({SelfimportBeanDefinitionRegistrar.class})
public class importConfig {
}
测试类:
@SpringBootTest
public class ImprotTest {
@Resource(name = "defaultTestService")
private TestService defaultTestService;
@Resource(name = "importTestService")
private TestService importTestService;
@Test
public void test3() {
defaultTestService.printInfo();
System.out.println(defaultTestService.toString());
importTestService.printInfo();
System.out.println(importTestService.toString());
}
}
测试结果:
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)