17. 数据类型转换工厂设计实现

工程结构

lqf-spring-step-17
├── main
│   ├── java
│   │   └── lqf
│   │       └── springframework
│   │           ├── aop
│   │           │   ├── AdvisedSupport.java
│   │           │   ├── Advisor.java
│   │           │   ├── BeforeAdvice.java
│   │           │   ├── ClassFilter.java
│   │           │   ├── MethodBeforeAdvice.java
│   │           │   ├── MethodMatcher.java
│   │           │   ├── Pointcut.java
│   │           │   ├── PointcutAdvisor.java
│   │           │   ├── TargetSource.java
│   │           │   ├── aspectj
│   │           │   │   ├── AspectJExpressionPointcut.java
│   │           │   │   └── AspectJExpressionPointcutAdvisor.java
│   │           │   └── framework
│   │           │       ├── AopProxy.java
│   │           │       ├── Cglib2AopProxy.java
│   │           │       ├── JdkDynamicAopProxy.java
│   │           │       ├── ProxyFactory.java
│   │           │       ├── ReflectiveMethodInvocation.java
│   │           │       ├── adapter
│   │           │       │   └── MethodBeforeAdviceInterceptor.java
│   │           │       └── autoproxy
│   │           │           └── DefaultAdvisorAutoProxyCreator.java
│   │           ├── beans
│   │           │   ├── BeansException.java
│   │           │   ├── PropertyValue.java
│   │           │   ├── PropertyValues.java
│   │           │   └── factory
│   │           │       ├── Aware.java
│   │           │       ├── BeanClassLoaderAware.java
│   │           │       ├── BeanFactory.java
│   │           │       ├── BeanFactoryAware.java
│   │           │       ├── BeanNameAware.java
│   │           │       ├── ConfigurableListableBeanFactory.java
│   │           │       ├── DisposableBean.java
│   │           │       ├── FactoryBean.java
│   │           │       ├── HierarchicalBeanFactory.java
│   │           │       ├── InitializingBean.java
│   │           │       ├── ListableBeanFactory.java
│   │           │       ├── ObjectFactory.java
│   │           │       ├── PropertyPlaceholderConfigurer.java
│   │           │       ├── annotation
│   │           │       │   ├── Autowired.java
│   │           │       │   ├── AutowiredAnnotationBeanPostProcessor.java
│   │           │       │   ├── Qualifier.java
│   │           │       │   └── Value.java
│   │           │       ├── config
│   │           │       │   ├── AutowireCapableBeanFactory.java
│   │           │       │   ├── BeanDefinition.java
│   │           │       │   ├── BeanFactoryPostProcessor.java
│   │           │       │   ├── BeanPostProcessor.java
│   │           │       │   ├── BeanReference.java
│   │           │       │   ├── ConfigurableBeanFactory.java
│   │           │       │   ├── InstantiationAwareBeanPostProcessor.java
│   │           │       │   └── SingletonBeanRegistry.java
│   │           │       ├── support
│   │           │       │   ├── AbstractAutowireCapableBeanFactory.java
│   │           │       │   ├── AbstractBeanDefinitionReader.java
│   │           │       │   ├── AbstractBeanFactory.java
│   │           │       │   ├── BeanDefinitionReader.java
│   │           │       │   ├── BeanDefinitionRegistry.java
│   │           │       │   ├── CglibSubclassingInstantiationStrategy.java
│   │           │       │   ├── DefaultListableBeanFactory.java
│   │           │       │   ├── DefaultSingletonBeanRegistry.java
│   │           │       │   ├── DisposableBeanAdapter.java
│   │           │       │   ├── FactoryBeanRegistrySupport.java
│   │           │       │   ├── InstantiationStrategy.java
│   │           │       │   └── SimpleInstantiationStrategy.java
│   │           │       └── xml
│   │           │           └── XmlBeanDefinitionReader.java
│   │           ├── context
│   │           │   ├── ApplicationContext.java
│   │           │   ├── ApplicationContextAware.java
│   │           │   ├── ApplicationEvent.java
│   │           │   ├── ApplicationEventPublisher.java
│   │           │   ├── ApplicationListener.java
│   │           │   ├── ConfigurableApplicationContext.java
│   │           │   ├── annotation
│   │           │   │   ├── ClassPathBeanDefinitionScanner.java
│   │           │   │   ├── ClassPathScanningCandidateComponentProvider.java
│   │           │   │   └── Scope.java
│   │           │   ├── event
│   │           │   │   ├── AbstractApplicationEventMulticaster.java
│   │           │   │   ├── ApplicationContextEvent.java
│   │           │   │   ├── ApplicationEventMulticaster.java
│   │           │   │   ├── ContextClosedEvent.java
│   │           │   │   ├── ContextRefreshedEvent.java
│   │           │   │   └── SimpleApplicationEventMulticaster.java
│   │           │   └── support
│   │           │       ├── AbstractApplicationContext.java
│   │           │       ├── AbstractRefreshableApplicationContext.java
│   │           │       ├── AbstractXmlApplicationContext.java
│   │           │       ├── ApplicationContextAwareProcessor.java
│   │           │       ├── ClassPathXmlApplicationContext.java
│   │           │       └── ConversionServiceFactoryBean.java
│   │           ├── core
│   │           │   ├── convert
│   │           │   │   ├── ConversionService.java
│   │           │   │   ├── converter
│   │           │   │   │   ├── Converter.java
│   │           │   │   │   ├── ConverterFactory.java
│   │           │   │   │   ├── ConverterRegistry.java
│   │           │   │   │   └── GenericConverter.java
│   │           │   │   └── support
│   │           │   │       ├── DefaultConversionService.java
│   │           │   │       ├── GenericConversionService.java
│   │           │   │       └── StringToNumberConverterFactory.java
│   │           │   └── io
│   │           │       ├── ClassPathResource.java
│   │           │       ├── DefaultResourceLoader.java
│   │           │       ├── FileSystemResource.java
│   │           │       ├── Resource.java
│   │           │       ├── ResourceLoader.java
│   │           │       └── UrlResource.java
│   │           ├── stereotype
│   │           │   └── Component.java
│   │           └── util
│   │               ├── ClassUtils.java
│   │               ├── NumberUtils.java
│   │               └── StringValueResolver.java
│   └── resources
└── test
    ├── java
    │   └── lqf
    │       └── springframework
    │           ├── SpringTest.java
    │           ├── bean
    │           │   └── Husband.java
    │           └── converter
    │               ├── ConvertersFactoryBean.java
    │               ├── StringToIntegerConverter.java
    │               └── StringToLocalDateConverter.java
    └── resources
        ├── spring.xml
        └── token.properties

设计

如果把看上去一个简单的类型转换操作抽象成框架,那么它就需要一个标准的接口,谁实现这个接口就具备类型转换的具体实现,提供类型转换的能力。那么在有了这样接口后,还需要类型转换服务的注册、工厂等内容,才可以把类型转换抽象成一个组件服务。整体设计结构如下图:

  • 首先从工厂出发,需要实现一个 ConversionServiceFactoryBean 来对类型转换服务进行操作。
  • 而实现类型转换的服务,需要定义 Converter 转换类型、ConverterRegistry 注册类型转换功能,另外转换类型的操作较多,所以这里也会需要定义一个类型转换工厂
    ConverterFactory 各个具体的转换操作来实现这个工厂接口。

实现

定义类型转换接口

类型转换处理接口: lqf.springframework.core.convert.converter.Converter
类型转换工厂: lqf.springframework.core.convert.converter.ConverterFactory
类型转换注册接口: lqf.springframework.core.convert.converter.ConverterRegistry

  • Converter、ConverterFactory、ConverterRegistry,都是用于自定义类型转换操作的相关接口,后续所有的实现都需要围绕这些接口来实现,具体的代码功能可以进行调试验证。

实现类型转换服务

类型转换服务: lqf.springframework.core.convert.support.DefaultConversionService

  • DefaultConversionService 是继承 GenericConversionService 的实现类,而 GenericConversionService 实现了
    ConversionService,ConverterRegistry 两个接口,用于 canConvert 判断和转换接口 convert 操作。

创建类型转换工厂

类型转换工厂: lqf.springframework.context.support.ConversionServiceFactoryBean

  • 有了 FactoryBean 的实现就可以完成工程对象的操作,可以提供出转换对象的服务 GenericConversionService, 另外在
    afterPropertiesSet 中调用了注册转换操作的类。最终这个类会被配置到 spring.xml 中在启动的过程加载。

类型转换服务使用

类型转换服务使用: lqf.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

  • 在 AbstractAutowireCapableBeanFactory#applyPropertyValues 填充属性的操作中,具体使用了类型转换的功能。
  • 在 AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues 也有同样的属性类型转换操作。

总结

  • 此处实现的类型转换操作如果只是功能性的开发,就像自己承接的需求那样,可能只是简单的if判断就搞定了,但是放在一个成熟的框架中要考虑的是可复用性、
    可拓展性,所以会看到接口的定义、工厂的使用等等设计模式在这里面体现。

    返回目录