【Spring源码解析】组件注册-@Import注解

@Import注解

@Import 注解支持导入普通 java 类,并将其声明成一个bean。主要用于将多个分散的 java config 配置类融合成一个更大的 config 类。

@Import 三种使用方式

  • 直接导入普通的 Java 类。
  • 配合自定义的 ImportSelector 使用。
  • 配合 ImportBeanDefinitionRegistrar 使用。

Configuration方式

  1. 创建一个普通类
1
2
3
4
5
public class Hi {
public void sayHello() {
System.out.println("Hello World");
}
}
  1. 创建一个配置类,里面没有显式声明任何的 Bean,然后将刚才创建的 Hi 导入
1
2
3
4
@Import(Hi.class)
@Configuration
public class HiConfig {
}
  1. 创建controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RestController
public class HiController {
@Autowired
Hi hi;
/**
* http://localhost:7777/hi
* 输出 Hello World
* @return
*/
@GetMapping("/hi")
public Object hi() {
hi.sayHello();
return "hi";
}
}

annotation方式

创建EnableHiConfig

1
2
3
4
5
6
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({Hi.class})
public @interface EnableHiConfig {
}

在application中加入注解@EnableHiConfig然后controller中即可调用

1
2
3
4
5
6
7
@EnableHiConfig
@SpringBootApplication
public class IdcMpApplication {
public static void main(String[] args) {
SpringApplication.run(IdcMpApplication.class, args);
}
}

ImportSelector

如果定义太多注解,那么在main方法上要添加太多注解…因此使用ImportSelector
ImportSelector 是一个接口,该接口中只有一个 selectImports 方法,用于返回全类名数组。所以利用该特性我们可以给容器动态导入 N 个 Bean。
因为这两个bean都是通过@Enable类型注解来将配置类注册到IOC容器中,所以我们现在要做的就是将这两个bean一次性都注册到IOC容器中。在Spring中,要将多个类进行注册,可以使用selector的方式。

创建HiSelector

1
2
3
4
5
6
7
8
public class HiSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{
Hi.class.getName()
};
}
}

创建EnableHiConfig

1
2
3
4
5
6
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({HiSelector.class})
public @interface EnableHiConfig {
}

在application中加入注解@EnableHiConfig然后controller中即可调用

ImportBeanDefinitionRegistrar

1
2
3
4
5
6
7
public class HiImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinition beanDefinition = new RootBeanDefinition(Hi.class);
registry.registerBeanDefinition("hi", beanDefinition);
}
}
1
2
3
4
5
6
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({HiImportBeanDefinitionRegistrar.class})
public @interface EnableHiConfig {
}

springboot源码中大多这种方式注入

IOC

IOC是一种编程思想, 由主动的编程改成被动的接收。

所谓IOC一句话搞定, 对象由spring来创建、管理、装配。

最后

本文到此结束,感谢阅读。如果您觉得不错,请关注公众号【当我遇上你】,您的支持是我写作的最大动力。