点此返回

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//模拟 @ComponentScan 注解的解析
//1、让自定义类实现 BeanDefinitionRegistryPostProcessor 接口
// 并重写 postProcessBeanFactory 方法
public class ComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override // context.refresh
public void postProcessBeanFactory
(ConfigurableListableBeanFactory configurableListableBeanFactory)
throws BeansException {

try {
//2、使用 AnnotationUtils 工具类从Config类中找到 @ComponentScan 注解对象
ComponentScan componentScan = AnnotationUtils
.findAnnotation(Config.class, ComponentScan.class);
if (componentScan != null) {
//3、不为空,获取包名(包名转换为classpath下的资源路径)
// com.itheima.a05.component
// -> classpath*:com/itheima/a05/component/**/*.class
for (String p : componentScan.basePackages()) {
String path = "classpath*:" + p.replace(".", "/") + "/**/*.class";

//4、读取类的元信息
CachingMetadataReaderFactory factory =
new CachingMetadataReaderFactory();
Resource[] resources =
new PathMatchingResourcePatternResolver().getResources(path);
AnnotationBeanNameGenerator generator =
new AnnotationBeanNameGenerator();

for (Resource resource : resources) {
MetadataReader reader = factory.getMetadataReader(resource);
//5、判断是否间接或者直接加了@Component注解
if (reader.getAnnotationMetadata()
.hasMetaAnnotation(Component.class.getName())
||
reader.getAnnotationMetadata()
.hasAnnotation(Component.class.getName())) {

//6、创建一个BeanDefinition
AbstractBeanDefinition bd = BeanDefinitionBuilder
.genericBeanDefinition(reader
.getClassMetadata()
.getClassName())
.getBeanDefinition();
if (configurableListableBeanFactory instanceof
DefaultListableBeanFactory beanFactory) {
//7、将BeanDefinition加入到Bean工厂
String beanName = generator.generateBeanName(bd, beanFactory);
beanFactory.registerBeanDefinition(beanName,bd);
}
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

当其他类使用时,只需要调用 context的 registerBean方法,并传入自定义类的.class即可

1
2
3
4
5
6
7
8
9
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean(ComponentScanPostProcessor.class);
//初始化容器
context.refresh();
//for (String name : context.getBeanDefinitionNames()) {
// System.out.println(name);
//}
//销毁容器
context.close();