上一篇文章中通过ConfigurationClassPostProcessor、MapperScannerConfigurer扫描到了Config类中定义的Bean信息。这篇文章来手动实现这些扫描类的功能。
如何扫描到定义的类加入到容器中?
BeanDefinitionRegistryPostProcessor接口继承BeanFactoryPostProcessor接口,在所有bean定义信息将要被加载,bean实例还没有创建的时候执行。BeanDefinitionRegistry是bean定义信息的保存中心,以后BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息创建bean实例
BeanDefinitionRegistryPostProcessor会在BeanFactoryPostProcessor之前执行,可以利用BeanDefinitionRegistryPostProcessor给容器中添加一些其它组件
自定义@ComponentScan处理器
思路:
1.通过 AnnotationUtils.findAnnotation 找到 ComponentScan注解
2.获取需要扫描的包
3.通过PathMatchingResourcePatternResolver获取包下的资源信息
4.通过CachingMetadataReaderFactory读取类的元数据信息
5.判断注解元信息上是否加了 @Component注解 或者 @Component派生类
6.生成BeanDefinition对象信息
7.BeanDefinition注入到beanFactory中
public class ComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override // context.refresh
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
try {
//1.通过 AnnotationUtils.findAnnotation 找到 ComponentScan注解
ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
if (componentScan != null) {
//2.获取需要扫描的包
for (String p : componentScan.basePackages()) {
String path = "classpath*:" + p.replace(".", "/") + "/**/*.class";
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
//3.通过PathMatchingResourcePatternResolver获取包下的资源信息
Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
for (Resource resource : resources) {
//4.通过CachingMetadataReaderFactory读取类的元数据信息
MetadataReader reader = factory.getMetadataReader(resource);
// System.out.println("类名:" + reader.getClassMetadata().getClassName());
AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
// System.out.println("是否加了 @Component:" + annotationMetadata.hasAnnotation(Component.class.getName()));
// System.out.println("是否加了 @Component 派生:" + annotationMetadata.hasMetaAnnotation(Component.class.getName()));
//5.判断注解元信息上是否加了 @Component注解 或者 @Component派生类
if (annotationMetadata.hasAnnotation(Component.class.getName())
|| annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
//6.生成BeanDefinition对象信息
AbstractBeanDefinition bd = BeanDefinitionBuilder
.genericBeanDefinition(reader.getClassMetadata().getClassName())
.getBeanDefinition();
String name = generator.generateBeanName(bd, beanFactory);
//7.BeanDefinition注入到beanFactory中
beanFactory.registerBeanDefinition(name, bd);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
自定义@Bean处理器
思路:
1.创建类的元信息读取的工厂类
2.读取Config类的元数据信息
3.获取定义了@Bean注解的方法
4.通过BeanDefinitionBuilder生成 BeanDefinition 对象信息
5.BeanDefinition 注册到 beanFactory 中
public class AtBeanPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
try {
//1.创建类的元信息读取的工厂类
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
//2.读取Config类的元数据信息
MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/study/spring/a05/Config.class"));
//3.获取定义了@Bean注解的方法
Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
for (MethodMetadata method : methods) {
System.out.println("AtBeanPostProcessor ==> " + method);
//4.通过BeanDefinitionBuilder生成 BeanDefinition 对象信息
String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
builder.setFactoryMethodOnBean(method.getMethodName(), "config");
//设置自动注入Bean的参数
builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
if (initMethod.length() > 0) {
builder.setInitMethodName(initMethod);
}
AbstractBeanDefinition bd = builder.getBeanDefinition();
//5.BeanDefinition 注册到 beanFactory 中
beanFactory.registerBeanDefinition(method.getMethodName(), bd);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
自定义@Mapper处理器
思路:
1.通过 PathMatchingResourcePatternResolver 读取mapper目录下的资源
2.读取类的元信息
3.判断类是否是接口 如果是接口创建类的实现类
4.通过 MapperFactoryBean 创建Mapper接口的实现类
5.通过类名称重新创建一个 BeanDefinition用来获取BeanName,因为上面通过MapperFactoryBean 创建的BeanDefinition 类名称都是相同的
6.BeanDefinition 注册到 beanFactory 中
public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
try {
//1.通过 PathMatchingResourcePatternResolver 读取mapper目录下的资源
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath:com/study/spring/a05/mapper/**/*.class");
AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
//2.读取类的元信息
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
for (Resource resource : resources) {
MetadataReader reader = factory.getMetadataReader(resource);
ClassMetadata classMetadata = reader.getClassMetadata();
//3.判断类是否是接口 如果是接口创建类的实现类
if (classMetadata.isInterface()) {
//4.通过 MapperFactoryBean 创建Mapper接口的实现类
AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class)
.addConstructorArgValue(classMetadata.getClassName())
.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
.getBeanDefinition();
//5.通过类名称重新创建一个 BeanDefinition ? 这里为什么要重新创建一个 ?
AbstractBeanDefinition bd2 = BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName()).getBeanDefinition();
String name = generator.generateBeanName(bd2, beanFactory);
//6.BeanDefinition 注册到 beanFactory 中
beanFactory.registerBeanDefinition(name, bd);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
测试
public static void main(String[] args) throws IOException {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("config", Config.class);
context.registerBean(ComponentScanPostProcessor.class); // 解析 @ComponentScan
context.registerBean(AtBeanPostProcessor.class); // 解析 @Bean
context.registerBean(MapperPostProcessor.class); // 解析 Mapper 接口
context.refresh();
for (String name : context.getBeanDefinitionNames()) {
System.out.println(name);
}
context.close();
}