17-SpringBoot自动配置-@Import详解

@Import详解

@Enable*底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到 IOC 容器中。

而 @Import 提供 4种用法:

  • 导入Bean
  • 导入配置类
  • 导入 ImportSelector 实现类。一般用户加载配置文件中的类
  • 导入 ImportBeanDefinitionRegistrar 实现类

案例演示

我们接着上一篇的项目继续演示。

1.【springboot-enable】使用@Import 导入 User 类


17-SpringBoot自动配置-@Import详解_bean

@SpringBootApplication
@Import(User.class)
public class SpringbootEnableApplication {

public static void main(String[] args) {
// 获取IOC容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
// 其他工程
Object user = context.getBean("user");
System.out.println(user);
}
}

其实使用 @Import(User.class) 是可以导入 bean 的,只是 bean 的名称不是 user,所以打印获取不到 user 名称的 bean,

我们不通过名称来获取 bean,采用类型来获取 bean,如下:


17-SpringBoot自动配置-@Import详解_bean_02

@SpringBootApplication
@Import(User.class)
public class SpringbootEnableApplication {

public static void main(String[] args) {
// 获取IOC容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
// 其他工程
// Object user = context.getBean("user");
Object user = context.getBean(User.class); // 使用类获取bean
System.out.println(user);
}

}

2.【springboot-enable】获取 IOC 容器中的 bean 映射 map

当然,如果我们希望获取类 bean 的名称,可以这样获取,如下:


17-SpringBoot自动配置-@Import详解_bean_03

@SpringBootApplication
@Import(User.class)
public class SpringbootEnableApplication {

public static void main(String[] args) {
// 获取IOC容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
// 其他工程
Object user = context.getBean(User.class);
System.out.println(user);

// 获取bean的名称
Map<String, User> map = context.getBeansOfType(User.class);
System.out.println(map);
}

}

3.【springboot-enable】使用@Import 导入 UserConfig 配置类

在上一篇中我们已经使用过导入配置类来获取 bean 了,不过之前我们的配置类只定义返回一个 bean 方法。现在我们来定义返回两个 bean。

3.1 【springboot-enable-other】新增 Role 类 以及配置  UserConfig 配置类返回 role bean


17-SpringBoot自动配置-@Import详解_spring_04

Role

package com.lijw.springbootenableother.domain;

public class Role {
}

UserConfig

package com.lijw.springbootenableother.config;

import com.lijw.springbootenableother.domain.Role;
import com.lijw.springbootenableother.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserConfig {

@Bean
public User user(){
return new User();
}

@Bean
public Role role(){
return new Role();
}
}

3.2 【springboot-enable】使用@Import 导入 UserConfig 配置类,验证获取配置类中的所有 bean


17-SpringBoot自动配置-@Import详解_java_05

package com.lijw.springbootenable;

import com.lijw.springbootenableother.config.UserConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;

import java.util.Map;

@SpringBootApplication
@Import(UserConfig.class)
public class SpringbootEnableApplication {

public static void main(String[] args) {
// 获取IOC容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
// 其他工程
Object user = context.getBean("user");
System.out.println(user);

Object role = context.getBean("role");
System.out.println(role);
}

}

通过结果来看,@Import 导入配置类是可以将配置类中定义的 @Bean 都放入的 IOC 容器内。

另外,如果是 @Import 导入的配置类,是不需要添加配置类注解 @Configuration 也可以配识别的,如下:


17-SpringBoot自动配置-@Import详解_spring boot_06

image-20220225130325914

4.【springboot-enable】导入 ImportSelector 实现类

4.1 首先搜索查看一下 ImportSelector 接口

public interface ImportSelector {

/**
* Select and return the names of which class(es) should be imported based on
* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
*/
String[] selectImports(AnnotationMetadata importingClassMetadata);

}

4.2 【springboot-enable-other】编写实现 ImportSelector 接口的类,设置需要产生 Bean 的类全限定名

17-SpringBoot自动配置-@Import详解_bean_07

package com.lijw.springbootenableother.config;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.lijw.springbootenableother.domain.User", "com.lijw.springbootenableother.domain.Role"};
}
}

返回的字符串数组 设置需要产生 bean 的类即可。

4.3 【springboot-enable】导入 ImportSelector 实现类,验证两个类的 bean

17-SpringBoot自动配置-@Import详解_spring_08

@SpringBootApplication
@Import(MyImportSelector.class)
public class SpringbootEnableApplication {

public static void main(String[] args) {
// 获取IOC容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
// 其他工程
Object user = context.getBean(User.class);
System.out.println(user);

Object role = context.getBean(Role.class);
System.out.println(role);
}

}

5.【springboot-enable】导入 ImportBeanDefinitionRegistrar 实现类

5.1 【springboot-enable-other】编写实现 ImportBeanDefinitionRegistrar 接口的类,设置需要产生 Bean 的类全限定名

17-SpringBoot自动配置-@Import详解_spring_09

package com.lijw.springbootenableother.config;

import com.lijw.springbootenableother.domain.Role;
import com.lijw.springbootenableother.domain.User;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// registry 可以用来向 IOC 容器注册类
// 注册user
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
registry.registerBeanDefinition("user", beanDefinition);

// 注册role
registry.registerBeanDefinition("role", BeanDefinitionBuilder.rootBeanDefinition(Role.class).getBeanDefinition());
}
}

5.2【springboot-enable】导入 ImportBeanDefinitionRegistrar 实现类,并验证生成的 bean

17-SpringBoot自动配置-@Import详解_mybatis_10

package com.lijw.springbootenable;


import com.lijw.springbootenableother.config.MyImportBeanDefinitionRegistrar;
import com.lijw.springbootenableother.config.MyImportSelector;
import com.lijw.springbootenableother.config.UserConfig;
import com.lijw.springbootenableother.domain.Role;
import com.lijw.springbootenableother.domain.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;

@SpringBootApplication
@Import(MyImportBeanDefinitionRegistrar.class)
public class SpringbootEnableApplication {

public static void main(String[] args) {
// 获取IOC容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
// 其他工程
Object user = context.getBean("user");
System.out.println(user);

Object role = context.getBean("role");
System.out.println(role);
}

}

可以看到也是成功生成了 bean 对象了。