spring 05 BeanFactory 后处理器
BeanFactory 后处理器的作用
- ConfigurationClassPostProcessor 可以解析
- @ComponentScan
- @Bean
- @Import
- @ImportResource
ConfigurationClassPostProcessor 具体作用
对于候选配置类使用CGLIB Enhancer增强
解析处理@PropertySource 注解
解析@ComponentScan注解,扫描@Configuration、@Service、@Controller、@Repository和@Component注解并注册BeanDefinition
解析@Import注解,然后进行实例化,并执行ImportBeanDefinitionRegistrar的registerBeanDefinitions逻辑,或者ImportSelector的selectImports逻辑
解析@ImportResource注解,并加载相关配置信息
解析方法级别@Bean注解并将返回值注册成BeanDefinition
注册ImportRegistry到容器中,用于处理ImportAware
- MapperScannerConfigurer 可以解析
- Mapper 接口
需要提前注册 DataSource 和 SqlSessionFactoryBean 否则报错
- Mapper 接口
点击查看代码
//创建干净的容器
GenericApplicationContext context = new GenericApplicationContext();
//将 Bean 加入容器
context.registerBean("s05Config",S05Config.class);
//加入 BeanFactory 后处理器
context.registerBean(ConfigurationClassPostProcessor.class);// 解析 @Bean、@ComponentScan、@Import、@ImportResource 等
//加入 Mybatis 提供的后处理器,解析 @Mapper
context.registerBean(MapperScannerConfigurer.class,bd->{
bd.getPropertyValues().add("basePackage","cn.xyf.spring.s05");});
//刷新容器
context.refresh();
-
@ComponentScan, @Bean, @Mapper 等注解的解析属于核心容器(即 BeanFactory)的扩展功能
-
这些扩展功能由不同的 BeanFactory 后处理器来完成,其实主要就是补充了一些 bean 定义
模拟解析 @ComponentScan
- Spring 操作元数据的工具类 CachingMetadataReaderFactory
- 通过注解元数据(AnnotationMetadata)获取直接或间接标注的注解信息
- 通过类元数据(ClassMetadata)获取类名,AnnotationBeanNameGenerator 生成 bean 名
- 解析元数据是基于 ASM 技术
自定义解析 @ComponentScan 处理器
public class MyComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override// context.refresh 初始化
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
@SneakyThrows
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory)throws BeansException {
//解析 @ComponentScan 利用 Spring 提供的工具类 AnnotationUtils
//1.得到 componentScan 注解
ComponentScan componentScan = AnnotationUtils.findAnnotation(S05Config.class, ComponentScan.class);
if (!Objects.isNull(componentScan)) {
//2.得到注解上的包名信息
for (String bp : componentScan.basePackages()) {
//3.拼接字符串变为资源路径
String path = "classpath*:" + bp.replace(".", "/") + "/**/*.class";
//4.根据路径得到资源
Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
//5.遍历资源通过 CachingMetadataReaderFactory 解析资源
CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
for (Resource resource : resources) {
MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(resource); //不走类加载,效率高
// System.out.println("类名是" + metadataReader.getClassMetadata().getClassName());
// System.out.println("是否有 @Component 注解" + metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));
// System.out.println("是否有 @Component 派生注解" + metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));
//6.判断是否加了 @Component 注解或其派生注解
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
if (annotationMetadata.hasAnnotation(Component.class.getName()) ||
annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
//7.将其变成 BeanDefinition 注册到容器中
//7.1通过 BeanDefinitionBuilder 得到 BeanDefinition
AbstractBeanDefinition beanDefinition
= BeanDefinitionBuilder.genericBeanDefinition(annotationMetadata.getClassName()).getBeanDefinition();
//7.2通过 AnnotationBeanNameGenerator 生成 BeanDefinition 的名字
AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator();
String beanName = annotationBeanNameGenerator.generateBeanName(beanDefinition, beanFactory);
//7.3通过 BeanFactory 注册 BeanDefinition
beanFactory.registerBeanDefinition(beanName,beanDefinition);
}
}
}
}
}
}
模拟解析 @Bean
熟悉注解元数据(AnnotationMetadata)获取方法上注解信息
点击查看代码
public class MyAtBeanPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry context) throws BeansException {
try {
CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(new ClassPathResource("cn/xyf/spring/s05/S05Config.class"));
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
Set<MethodMetadata> methods = annotationMetadata.getAnnotatedMethods(Bean.class.getName());
for (MethodMetadata method : methods) {
String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
BeanDefinitionBuilder builder =
beanDefinitionBuilder.setFactoryMethodOnBean(method.getMethodName(), "s05Config");
builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
if (initMethod.length() > 0) {
builder.setInitMethodName(initMethod);
}
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
context.registerBeanDefinition(method.getMethodName(),beanDefinition);
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("初始化了");
}
}
模拟解析 Mapper 接口
@Bean
public MapperFactoryBean<S05Mapper1> s05Mapper1(SqlSessionFactory sqlSessionFactory) {
MapperFactoryBean<S05Mapper1> factoryBean = new MapperFactoryBean<>(S05Mapper1.class);
factoryBean.setSqlSessionFactory(sqlSessionFactory);
return factoryBean;
}
@Bean
public MapperFactoryBean<S05Mapper2> s05Mapper2(SqlSessionFactory sqlSessionFactory) {
MapperFactoryBean<S05Mapper2> factoryBean = new MapperFactoryBean<>(S05Mapper2.class);
factoryBean.setSqlSessionFactory(sqlSessionFactory);
return factoryBean;
}
-
Mapper 接口被 Spring 管理的本质:实际是被作为 MapperFactoryBean 注册到容器中
-
Spring 的诡异做法,根据接口生成的 BeanDefinition 仅为根据接口名生成 bean 名
点击查看代码
public class MyMapperPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
try {
PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver
= new PathMatchingResourcePatternResolver();
AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator();
Resource[] resources =
pathMatchingResourcePatternResolver.getResources("classpath:cn/xyf/spring/s05/mapper/**/*.class");
CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
for (Resource resource : resources) {
MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(resource);
System.out.println(metadataReader.getClassMetadata().getClassName());
ClassMetadata classMetadata = metadataReader.getClassMetadata();
if (classMetadata.isInterface()) {
AbstractBeanDefinition beanDefinition
= BeanDefinitionBuilder
.genericBeanDefinition(MapperFactoryBean.class)
.addConstructorArgValue(classMetadata.getClassName()) //添加构造的参数
.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
.getBeanDefinition();
AbstractBeanDefinition mapperBD =
BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName()).getRawBeanDefinition();
String beanName = annotationBeanNameGenerator.generateBeanName(mapperBD, beanFactory);
beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}

浙公网安备 33010602011771号