工厂后处理器

常用工厂后处理器

准备如下的案例代码
notion image
@Component public class Bean2 { private static final Logger log = LoggerFactory.getLogger(Bean2.class); public Bean2() { log.debug("我被 Spring 管理啦"); } }
@Controller public class Bean3 { private static final Logger log = LoggerFactory.getLogger(Bean3.class); public Bean3() { log.debug("我被 Spring 管理啦"); } }
public class Bean4 { private static final Logger log = LoggerFactory.getLogger(Bean4.class); public Bean4() { log.debug("我被 Spring 管理啦"); } }
public class Bean1 { private static final Logger log = LoggerFactory.getLogger(Bean1.class); public Bean1() { log.debug("我被 Spring 管理啦"); } }
@Configuration @ComponentScan("com.onethink.a05.component") public class Config { @Bean public Bean1 bean1() { return new Bean1(); } @Bean public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); return sqlSessionFactoryBean; } @Bean(initMethod = "init") public DruidDataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/test"); dataSource.setUsername("root"); dataSource.setPassword("root"); return dataSource; } /*@Bean public MapperFactoryBean<Mapper1> mapper1(SqlSessionFactory sqlSessionFactory) { MapperFactoryBean<Mapper1> factory = new MapperFactoryBean<>(Mapper1.class); factory.setSqlSessionFactory(sqlSessionFactory); return factory; } @Bean public MapperFactoryBean<Mapper2> mapper2(SqlSessionFactory sqlSessionFactory) { MapperFactoryBean<Mapper2> factory = new MapperFactoryBean<>(Mapper2.class); factory.setSqlSessionFactory(sqlSessionFactory); return factory; }*/ }

ConfigurationClassPostProcessor

处理@ComponentScan @Bean @Import @ImportResource 等注解
public class A05 { private static final Logger log = LoggerFactory.getLogger(A05.class); public static void main(String[] args) throws IOException { // ⬇️GenericApplicationContext 是一个【干净】的容器 GenericApplicationContext context = new GenericApplicationContext(); context.registerBean("config", Config.class); // ⬇️初始化容器 context.refresh(); for (String name : context.getBeanDefinitionNames()) { System.out.println(name); } // ⬇️销毁容器 context.close(); } }
spring容器里只有config对象
notion image
注册后置处理器ConfigurationClassPostProcessor
public class A05 { private static final Logger log = LoggerFactory.getLogger(A05.class); public static void main(String[] args) throws IOException { // ⬇️GenericApplicationContext 是一个【干净】的容器 GenericApplicationContext context = new GenericApplicationContext(); context.registerBean("config", Config.class); context.registerBean(ConfigurationClassPostProcessor.class); // @ComponentScan @Bean @Import @ImportResource // ⬇️初始化容器 context.refresh(); for (String name : context.getBeanDefinitionNames()) { System.out.println(name); } // Mapper1 mapper1 = context.getBean(Mapper1.class); // Mapper2 mapper2 = context.getBean(Mapper2.class); // ⬇️销毁容器 context.close(); /* 学到了什么 a. @ComponentScan, @Bean, @Mapper 等注解的解析属于核心容器(即 BeanFactory)的扩展功能 b. 这些扩展功能由不同的 BeanFactory 后处理器来完成, 其实主要就是补充了一些 bean 定义 */ } }
@ComponentScan @Bean 注解生效
 
[DEBUG] 08:48:15.965 [main] com.onethink.a05.component.Bean2 - 我被 Spring 管理啦 [DEBUG] 08:48:15.968 [main] com.onethink.a05.component.Bean3 - 我被 Spring 管理啦 [DEBUG] 08:48:15.977 [main] com.onethink.a05.Bean1 - 我被 Spring 管理啦 [INFO ] 08:48:16.083 [main] c.a.druid.pool.DruidDataSource - {dataSource-1} inited config org.springframework.context.annotation.ConfigurationClassPostProcessor bean2 bean3 bean1 sqlSessionFactoryBean dataSource [INFO ] 08:48:16.130 [main] c.a.druid.pool.DruidDataSource - {dataSource-1} closing ... [INFO ] 08:48:16.131 [main] c.a.druid.pool.DruidDataSource - {dataSource-1} closed Process finished with exit code 0
但是并没有实例化mapper

MapperScannerConfigurer

解析并处理@MapperScanner 注解
public class A05 { private static final Logger log = LoggerFactory.getLogger(A05.class); public static void main(String[] args) throws IOException { // ⬇️GenericApplicationContext 是一个【干净】的容器 GenericApplicationContext context = new GenericApplicationContext(); context.registerBean("config", Config.class); context.registerBean(ConfigurationClassPostProcessor.class); // @ComponentScan @Bean @Import @ImportResource context.registerBean(MapperScannerConfigurer.class, bd -> { // @MapperScanner bd.getPropertyValues().add("basePackage", "com.onethink.a05.mapper"); }); // ⬇️初始化容器 context.refresh(); for (String name : context.getBeanDefinitionNames()) { System.out.println(name); } // Mapper1 mapper1 = context.getBean(Mapper1.class); // Mapper2 mapper2 = context.getBean(Mapper2.class); // ⬇️销毁容器 context.close(); /* 学到了什么 a. @ComponentScan, @Bean, @Mapper 等注解的解析属于核心容器(即 BeanFactory)的扩展功能 b. 这些扩展功能由不同的 BeanFactory 后处理器来完成, 其实主要就是补充了一些 bean 定义 */ } }
notion image
 

总结💡

  • ConfigurationClassPostProcessor 可以解析
    • @ComponentScan
    • @Bean
    • @Import
    • @ImportResource
  • MapperScannerConfigurer 可以解析
    • Mapper 接口
  1. @ComponentScan, @Bean, @Mapper 等注解的解析属于核心容器(即 BeanFactory)的扩展功能
  1. 这些扩展功能由不同的 BeanFactory 后处理器来完成,其实主要就是补充了一些 bean 定义

模拟工厂后处理器

  1. Spring 操作元数据的工具类 CachingMetadataReaderFactory
  1. 通过注解元数据(AnnotationMetadata)获取直接或间接标注的注解信息
  1. 通过类元数据(ClassMetadata)获取类名,AnnotationBeanNameGenerator 生成 bean 名
  1. 解析元数据是基于 ASM 技术

模拟ComponentScan

public class ComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override // context.refresh public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException { try { ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class); if (componentScan != null) { for (String p : componentScan.basePackages()) { System.out.println(p); // com.onethink.a05.component -> classpath*:com/onethink/a05/component/**/*.class String path = "classpath*:" + p.replace(".", "/") + "/**/*.class"; System.out.println(path); CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory(); Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path); AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator(); for (Resource resource : resources) { // System.out.println(resource); 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())); if (annotationMetadata.hasAnnotation(Component.class.getName()) || annotationMetadata.hasMetaAnnotation(Component.class.getName())) { AbstractBeanDefinition bd = BeanDefinitionBuilder .genericBeanDefinition(reader.getClassMetadata().getClassName()) .getBeanDefinition(); String name = generator.generateBeanName(bd, beanFactory); beanFactory.registerBeanDefinition(name, bd); } } } } } catch (IOException e) { e.printStackTrace(); } } }
 

模拟Bean后置处理器

public class AtBeanPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException { try { CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory(); MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/onethink/a05/Config.class")); Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName()); for (MethodMetadata method : methods) { System.out.println(method); String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString(); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); builder.setFactoryMethodOnBean(method.getMethodName(), "config"); builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); if (initMethod.length() > 0) { builder.setInitMethodName(initMethod); } AbstractBeanDefinition bd = builder.getBeanDefinition(); beanFactory.registerBeanDefinition(method.getMethodName(), bd); } } catch (IOException e) { e.printStackTrace(); } } }

模拟mapper后置处理器

public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException { try { PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource[] resources = resolver.getResources("classpath:com/onethink/a05/mapper/**/*.class"); AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator(); CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory(); for (Resource resource : resources) { MetadataReader reader = factory.getMetadataReader(resource); ClassMetadata classMetadata = reader.getClassMetadata(); if (classMetadata.isInterface()) { AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class) .addConstructorArgValue(classMetadata.getClassName()) .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE) .getBeanDefinition(); AbstractBeanDefinition bd2 = BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName()).getBeanDefinition(); String name = generator.generateBeanName(bd2, beanFactory); beanFactory.registerBeanDefinition(name, bd); } } } catch (IOException e) { e.printStackTrace(); } } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } }