ioc原理3 :自定義匯入器
阿新 • • 發佈:2020-12-13
問題引入
在通常情況下,bean只有通過配置才可以進入spring容器,被spring載入並控制
配置bean的方式如下:
1.XML檔案方式配置
2.使用註解方式配置
然而? 如果現在由大量的bean需要配置,那麼需要一個一個去配置嗎?
此時就需要一個匯入器快速高效配置大量的bean
例如:
現在這個類並沒有添加註解和配置然後將它放到spring容器中
自定義匯入器
1.定義一個類實現ImportSelector介面重寫selectImports方法
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 1.程式設計形式載入一個類
// return new String[]{"com.itheima.dao.impl.BookDaoImpl"};
// 2.載入import.properties檔案中的單個類名
// ResourceBundle bundle = ResourceBundle.getBundle("import");
// String className = bundle.getString("className");
// 3.載入import.properties檔案中的多個類名
ResourceBundle bundle = ResourceBundle.getBundle("import");
String className = bundle.getString("className");
return className.split(",");
}
}
improt.properties
如果說需要匯入某個包下的類
path=com.itheima.dao.impl.*
匯入器工具類 複製修改配置檔名即可
public class CustomerImportSelector implements ImportSelector {
private String expression;
public CustomerImportSelector(){
try {
//初始化時指定載入的properties檔名
Properties loadAllProperties = PropertiesLoaderUtils.loadAllProperties("import.properties");
//設定載入的屬性名
expression = loadAllProperties.getProperty("path");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//1.定義掃描包的名稱
String[] basePackages = null;
//2.判斷有@Import註解的類上是否有@ComponentScan註解
if (importingClassMetadata.hasAnnotation(ComponentScan.class.getName())) {
//3.取出@ComponentScan註解的屬性
Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName());
//4.取出屬性名稱為basePackages屬性的值
basePackages = (String[]) annotationAttributes.get("basePackages");
}
//5.判斷是否有此屬性(如果沒有ComponentScan註解則屬性值為null,如果有ComponentScan註解,則basePackages預設為空陣列)
if (basePackages == null || basePackages.length == 0) {
String basePackage = null;
try {
//6.取出包含@Import註解類的包名
basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//7.存入陣列中
basePackages = new String[] {basePackage};
}
//8.建立類路徑掃描器
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
//9.建立型別過濾器(此處使用切入點表示式型別過濾器)
TypeFilter typeFilter = new AspectJTypeFilter(expression,this.getClass().getClassLoader());
//10.給掃描器加入型別過濾器
scanner.addIncludeFilter(typeFilter);
//11.建立存放全限定類名的集合
Set<String> classes = new HashSet<>();
//12.填充集合資料
for (String basePackage : basePackages) {
scanner.findCandidateComponents(basePackage).forEach(beanDefinition -> classes.add(beanDefinition.getBeanClassName()));
}
//13.按照規則返回
return classes.toArray(new String[classes.size()]);
}
}