【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】
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 {@Overridepublic 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 {@Overridepublic 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 {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {System.out.println("===========================");System.out.println(importingClassMetadata.getClassName());System.out.println(importingClassMetadata.hasAnnotation("org.springframework.context.annotation.Configuration"));Map 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 {@Overridepublic 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