We know that there are many ways to register beans into IOC, such as XML, JavaConfig including :(@compent, @service, @controller, @repository, @bean), etc. But apart from the above, is there any other way to hand over our objects to IOC for its management? The answer is definitely yes!! It is @ the Import ();
@import Supports three types of imports.
- Ordinary class
- Configuration classes (such as those modified by Configuration)
- Implements the ImportSelector
(Optionally imported into IOC
) ` interface- ImportBeanDefinitionRegistrar interface is realized
(You can add bean definition information to Spring (using RootBeanDefinition's registerBeanDefinition method) to create and manage beans by Spring.)
Here we give examples and test them
1. Import ordinary classes into the IOC container
Let’s give it a try(Note that I crossed out @Configuration in ImportJavaConfigList)
Hey hey wrong report. Add at sign Configuration and let’s see
Ok, the normal EmailService class can now be registered with the Spring container.
2. Import the Configuration class to the IOC container
As shown in figure, can see RedisTemplateExample run by the spring, and some people say that I don’t @ Import also line ah, spring will be scanned to RedisConfigurationExample configuration classes to create bean ah, here I want to say is, In fact, I think the @import argument, XXX. Class, is more of a configuration class in a non-SpringBoot boot project, for example: If I have an admin service (a Springboot project) and admin needs to rely on common’s POM file, common is a non-Springboot application, You can either specify a path to scan the xxx.class configuration class in common (such as @scan(“com.xzll.*”)) or Import the xxx.class using @import.
3. Import the class that implements the ImportSelector interface into the IOC container
Here we simulate a scenario where different beans are used to send alarm messages depending on the annotation value.
3.1 Define an annotation EnableAlarmNotice
/ * * *@Author: hzz
* @Date: 2021/9/18 16:33:34
* @Description: loads the SpringBoot boot class used to specify which alarm methods to enable */
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@Import(AlarmServiceSelector.class)
public @interface EnableAlarmNotice {
String[] types() default {"ding_ding"};
}
Copy the code
3.2 Customizing a selector(Get different beans according to types annotated above)
Implement ImportSelector
/ * * *@Author: hzz
* @Date: 2021/9/18 17:01:08
* @DescriptionThe alarm mode selector optionally injects bean */ according to the types field in the EnableAlarmNotice annotation
public class AlarmServiceSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// Get the type on the annotation and optionally create the bean from the Types array into IOC
Map<String, Object> map = annotationMetadata.getAnnotationAttributes(EnableAlarmNotice.class.getName(), true);
List<String> needInIOCBean = new ArrayList<>();
if(map ! =null && !map.isEmpty()) {
String[] types = (String[]) map.get("types");
if (Objects.isNull(types) || types.length == 0)
return new String[0];
for (int i = 0; i < types.length; i++) { needInIOCBean.add(AlarmNoticeTypeEnum.getClassFullName(types[i])); }}return needInIOCBean.toArray(new String[0]); }}Copy the code
3.3 Make an enumeration to define the alarm method and the full class name of the bean
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum AlarmNoticeTypeEnum {
EMAIL("email"."com.xzll.common.alarm.service.impl.EmailAlarmNoticeImpl"),
DING_DING("ding_ding"."com.xzll.common.alarm.service.impl.DingDingAlarmNoticeImpl");
private String type;
private String classFullName;
public static String getClassFullName(String type) {
AlarmNoticeTypeEnum[] var1 = values();
int var2 = var1.length;
for (int var3 = 0; var3 < var2; ++var3) {
AlarmNoticeTypeEnum alarmNoticeTypeEnum = var1[var3];
if (Objects.equals(alarmNoticeTypeEnum.type, type)) {
returnalarmNoticeTypeEnum.getClassFullName(); }}returnStringUtils.EMPTY; }}Copy the code
3.4 Enable and set annotations in the startup classDing_ding and email
Two values
@SpringBootTest(classes = StudyTestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@RunWith(SpringJUnit4ClassRunner.class)
@EnableRabbitMq
@EnableAlarmNotice( types= {"ding_ding", "email"})
@Slf4j
public class StudyTestApplicationTest {}Copy the code
3.5 Run unit tests to see the results
However, I found that the id of the bean registered with @service is different from that of the bean registered with ImportSelector. Note this in practice as follows:
Ok that’s it for the ImportSelector
4. Import class implements ImportBeanDefinitionRegistrar interface to the IOC container
4.1 we implement ImportBeanDefinitionRegistrar interface, and rewrite the method, and then the method of the bean information can be modified or increased.
As follows:
Ok, that’s all for today about the @import annotation. I have time to compile an article about its source code. I believe you will have a deeper understanding of this annotation. The day after tomorrow, I wish you a happy Mid-Autumn Festival!!