SpringBoot
【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】
SpringBoot 原理篇
文章目录
- SpringBoot
- SpringBoot 原理篇
- 1 自动配置
- 1.8 bean 的加载方式【六】
- 1.8.1 ImportSelector
1 自动配置
1.8 bean 的加载方式【六】
1.8.1 ImportSelector
OK,上一节又说完了第五种
使用上下文对象在容器初始化完毕后注入bean
下面就来说说第六种
第六种方式平时咱们自己用的少,但是在框架内部大量使用
先来一个全新的类
package com.dingjiaxiong.bean;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* ClassName: MyImportSelector
* date: 2022/10/24 15:39
*
* @author DingJiaxiong
*/
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.dingjiaxiong.bean.Dog"};
}
}
数组中是要加载bean 的全路径名
再来一个新的配置类
package com.dingjiaxiong.config;
import com.dingjiaxiong.bean.Dog;
import com.dingjiaxiong.bean.MyImportSelector;
import org.springframework.context.annotation.Import;
/**
* ClassName: SpringConfig6
* date: 2022/10/24 14:52
*
* @author DingJiaxiong
*/
@Import(MyImportSelector.class)
public class SpringConfig6 {
}
最后来个运行类
package com.dingjiaxiong.app;
import com.dingjiaxiong.bean.Cat;
import com.dingjiaxiong.bean.Mouse;
import com.dingjiaxiong.config.SpringConfig4;
import com.dingjiaxiong.config.SpringConfig6;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* ClassName: App6
* date: 2022/10/24 13:42
*
* @author DingJiaxiong
*/
public class App6 {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig6.class);
String[] names = ctx.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
System.out.println("=========================");
}
}
OK,直接运行
OK, 效果很明显,已经上来了
还可以写多个
没毛病
加载就是这样了,难免会有人想问,为嘛要折腾这?
这种方式的关键
在于这个东西
Metadata 元数据:
举个例子,我们造了一个数据库、表,表里面有数据,那么这个数据表的信息在哪儿描述?
还得有另外一张表来描述这张表的结构,那这另外这张表就可以称为被描述表的元数据
还可以有元元数据、元元元数据…【数据库中有四层】
在我们这儿,元数据就是往上追溯一下
【这个东西有什么用?】
修改一下
package com.dingjiaxiong.bean;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* ClassName: MyImportSelector
* date: 2022/10/24 15:39
*
* @author DingJiaxiong
*/
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println(importingClassMetadata.getClassName());
return new String[]{"com.dingjiaxiong.bean.Dog"};
}
}
先拿个classname 看看
意思就是 importingClassMetadata 这个形参描述的是 SpringConfig6
简单的说,
加载的是谁,描述的就是谁
再来
System.out.println(importingClassMetadata.hasAnnotation("org.springframework.context.annotation.Configuration"));
这个意思就是描述的那个东西上面有没有Configuration 注解
直接看看
如果我注掉
这样就false了
所以现在就可以明确了 importingClassMetadata 这个指的就是它那个类出现在谁上面
意思就是SpringConfig6 就是它对应的元数据
再来一个
现在我想知道,它有没有加basePackages 这个属性
package com.dingjiaxiong.bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import java.util.Map;
/**
* ClassName: MyImportSelector
* date: 2022/10/24 15:39
*
* @author DingJiaxiong
*/
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("===========================");
System.out.println(importingClassMetadata.getClassName());
System.out.println(importingClassMetadata.hasAnnotation("org.springframework.context.annotation.Configuration"));
Map<String, Object> attributes = importingClassMetadata.getAnnotationAttributes("org.springframework.context.annotation.ComponentScan");
System.out.println(attributes);
System.out.println("===========================");
return new String[]{"com.dingjiaxiong.bean.Dog"};
}
}
OK,直接运行
OK, 没啥毛病
到现在大概就知道了,我们可以利用这个东西去做一系列的判定,ImportSelector 的意义就在于我们可以进行各种条件的判定,判定完毕后,决定是否装载指定的bean
举个栗子
package com.dingjiaxiong.bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import java.util.Map;
/**
* ClassName: MyImportSelector
* date: 2022/10/24 15:39
*
* @author DingJiaxiong
*/
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
boolean flag = importingClassMetadata.hasAnnotation("org.springframework.context.annotation.Configuration");
if (flag){
return new String[]{"com.dingjiaxiong.bean.Dog"};
}
return new String[]{"com.dingjiaxiong.bean.Cat"};
}
}
判定运行结果
就是这样,意思就是这个东西不仅能够加载bean,它还可以进行条件判定、然后控制加载谁
OK,回顾一下
导入实现了ImportSelector接口的类,实现对导入源的编程式处理
相当于现在谁导入这个类,它就可以查谁的户口
SpringConfig6 导入了它,它就可以查SpringConfig6 的户口
OK