bean
yaml配置Bean
单点注入
@Value("${键名}")
1 2 3
| email: user: nash password: 798596
|
1 2 3 4 5 6 7 8 9
| @Component public class EmailProperties{ @Value("${email.user}") public String user; @Value("${email.password}") public String code; }
|
结构化注入
利用@ConfigurationProperties(prefix="前缀"),
添加后该类自动将成员变量匹配上yml文件的字段
1 2 3
| email: user: nash password: 123
|
1 2 3 4 5 6
| @Component @ConfigurationProperties(prefix = "email") public class EmailProperties { private String user; private String password; }
|
bean管理
bean的注册
| 注解 |
说明 |
位置 |
| @Component |
声明bean的基础注解 |
不属于以下三类时,用此注解 |
| @Controller |
@Component的衍生注解 |
标注在控制器类上 |
| @Service |
@Component的衍生注解 |
标注在业务类上 |
| @Repository |
@Component的衍生注解 |
标注在数据访问类上(由于与mybatis整合,用的少) |
流程
默认扫描规则 :
*Spring Boot 默认扫描“启动类所在包”及其子包*
导入第三方bean到容器
bug
第三方bean无妨用@Component及其衍生注解bean
解决
1.配置类 @Configuration + @Bean
写一个Config类并用@Configuration修饰, 启动即扫此类
在配置类编写方法, 方法的返回值即为 第三方bean
第三方bean需要依赖其他已注入的bean时,
将已注入的bean作为形参
2.@Import + @Bean
- 在启动类加 @Import(配置类.class),
多个可以写成数组@Import({,,,})
- 如果实在太多可以导入ImportSelector接口的实现类, 然后重写selectImports方法, 返回我们需要导入的包(是一个String[]{“”,””,””})
- 耦合度太高, 不够动态
3.配置文件
1 2 3 4 5 6 7 8 9 10
| 配置文件 common.imports ↓ 把要导入的配置类全写进去 ↓ ImportSelector 读取这个文件 ↓ 把类名返回给 Spring ↓ Spring 按这些类名去注册 bean
|
配置文件导入法里,配置文件保存的是要导入的配置类全限定名,
ImportSelector 负责读取这些类名并返回 String[],
再通过 @Import(ImportSelector实现类.class) 让 Spring 加载这些配置类,最终由配置类中的 @Bean 注册第三方 bean。
3.1 resources/common.imports
此文件即名单表, 里面一般写:
1 2 3
| com.xxx.AConfig com.xxx.BConfig com.xxx.CConfig
|
意即这些类导入到Spring容器中
注意这里写的是配置类的路径, 而不是Bean!!!!
Bean一般写在配置类里面作为方法的返回值返回
3.2 CommonImportSelector
核心方法:
1
| public String[] selectImports(...)
|
返回的即为我们要导入的类
3.2.1 读配置文件
1 2 3
| InputStream is = CommonImportSelector.class .getClassLoader() .getResourceAsStream("common.imports");
|
此时会读取所有的配置类, 并且把所有@Bean修饰的都去注册为第三方bean
3.2.2 实现ImportSelector接口
在ImportSelector接口的子实现类中重写方法selectImports方法, 并且封装成String[]作为返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public String[] selectImports(AnnotationMetadata importingClassMetadata) {
List<String> imports = new ArrayList<>(); InputStream is = CommonImportSelector.class .getClassLoader() .getResourceAsStream("common.imports"); var br = new BufferedReader(new InputStreamReader(is)); String line = null; try { while ((line = br.readLine()) != null) { imports.add(line); } } catch (IOException e) { throw new RuntimeException(e); } finally { if (br != null) { try { br.close(); } catch (IOException e) { throw new RuntimeException(e); } } } return imports.toArray(new String[0]); }
|
3.2.3 @Import(CommonImportSelector.class)
//ImportSelector接口的子实现类.class
1 2 3 4 5 6 7 8 9 10 11 12 13
| 启动类启动 ↓ 看到 @Import(CommonImportSelector.class) ↓ 执行 CommonImportSelector ↓ 读取 common.imports ↓ 拿到配置类名 ↓ 导入这些配置类 ↓ 配置类里的 @Bean 生效
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| @SpringBootApplication @Import(CommonImportSelector.class) public class SpringbootRegisterApplication {
public static void main(String[] args) { ApplicationContext context = SpringApplication.run(SpringbootRegisterApplication.class, args);
Country country = context.getBean(Country.class); System.out.println(country);
System.out.println(context.getBean("province")); } }
|