手搓spring迷你框架之旅-05 新项目的启动

手搓spring迷你框架之旅-05 新项目的启动

因为种种原因 本人不得不放弃之前开发的四部分 四部分就当一个小框架来实现了最简单的扫包 注册bean并且操作 就只在于让我初步了解了spring的最基本的工作原理 在本人的思考下 准备进军更复杂完善的手写spring项目的行动 愿成功

image-plmx.png

本篇将会实现最基本的IOC容器结构与实现(从一个轮子新手的视角 一步一步完成)

项目结构树(github上的minispring项目)

├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─minispring
│  │  │          ├─aop
│  │  │          │  │  Advice.java
│  │  │          │  │  Advisor.java
│  │  │          │  │  AfterAdvice.java
│  │  │          │  │  AfterReturningAdvice.java
│  │  │          │  │  BeforeAdvice.java
│  │  │          │  │  ClassFilter.java
│  │  │          │  │  MethodBeforeAdvice.java
│  │  │          │  │  MethodMatcher.java
│  │  │          │  │  Pointcut.java
│  │  │          │  │  PointcutAdvisor.java
│  │  │          │  │  TargetSource.java
│  │  │          │  │  TruePointcut.java
│  │  │          │  │  
│  │  │          │  ├─aspectj
│  │  │          │  │      AspectJExpressionPointcut.java
│  │  │          │  │      
│  │  │          │  ├─framework
│  │  │          │  │      AdvisedSupport.java
│  │  │          │  │      AopProxy.java
│  │  │          │  │      CglibAopProxy.java
│  │  │          │  │      JdkDynamicAopProxy.java
│  │  │          │  │      MethodInvocation.java
│  │  │          │  │      ProxyFactory.java
│  │  │          │  │      ReflectiveMethodInvocation.java
│  │  │          │  │      SingletonTargetSource.java
│  │  │          │  │      TargetSource.java
│  │  │          │  │      
│  │  │          │  └─support
│  │  │          │          DefaultPointcutAdvisor.java
│  │  │          │          
│  │  │          ├─beans
│  │  │          │  │  BeansException.java
│  │  │          │  │  BeanWrapper.java
│  │  │          │  │  PropertyValue.java
│  │  │          │  │  PropertyValues.java
│  │  │          │  │  SimpleTypeConverter.java
│  │  │          │  │  TypeConverter.java
│  │  │          │  │  TypeMismatchException.java
│  │  │          │  │  
│  │  │          │  └─factory
│  │  │          │      │  AutowireCapableBeanFactory.java
│  │  │          │      │  BeanFactory.java
│  │  │          │      │  BeanFactoryAware.java
│  │  │          │      │  BeanNameAware.java
│  │  │          │      │  ConfigurableBeanFactory.java
│  │  │          │      │  ConfigurableListableBeanFactory.java
│  │  │          │      │  DisposableBean.java
│  │  │          │      │  HierarchicalBeanFactory.java
│  │  │          │      │  InitializingBean.java
│  │  │          │      │  ListableBeanFactory.java
│  │  │          │      │  ObjectFactory.java
│  │  │          │      │  
│  │  │          │      ├─config
│  │  │          │      │      BeanDefinition.java
│  │  │          │      │      BeanFactoryPostProcessor.java
│  │  │          │      │      BeanPostProcessor.java
│  │  │          │      │      BeanReference.java
│  │  │          │      │      ConfigurableBeanFactory.java
│  │  │          │      │      DependencyDescriptor.java
│  │  │          │      │      PlaceholderResolver.java
│  │  │          │      │      PropertyPlaceholderResolver.java
│  │  │          │      │      PrototypeScope.java
│  │  │          │      │      Scope.java
│  │  │          │      │      ScopedBeanFactoryPostProcessor.java
│  │  │          │      │      ScopedProxyBeanPostProcessor.java
│  │  │          │      │      ScopedProxyFactory.java
│  │  │          │      │      ScopeRegistrar.java
│  │  │          │      │      SingletonBeanRegistry.java
│  │  │          │      │      SingletonScope.java
│  │  │          │      │      
│  │  │          │      ├─support
│  │  │          │      │      AbstractAutowireCapableBeanFactory.java
│  │  │          │      │      AbstractBeanDefinitionReader.java
│  │  │          │      │      AbstractBeanFactory.java
│  │  │          │      │      BeanDefinitionReader.java
│  │  │          │      │      BeanDefinitionRegistry.java
│  │  │          │      │      CglibSubclassingInstantiationStrategy.java
│  │  │          │      │      ConstructorResolver.java
│  │  │          │      │      DefaultListableBeanFactory.java
│  │  │          │      │      DefaultSingletonBeanRegistry.java
│  │  │          │      │      DisposableBeanAdapter.java
│  │  │          │      │      InstantiationStrategy.java
│  │  │          │      │      SimpleInstantiationStrategy.java
│  │  │          │      │      
│  │  │          │      └─xml
│  │  │          │              AbstractNamespaceHandler.java
│  │  │          │              BeanDefinitionDocumentReader.java
│  │  │          │              ContextNamespaceHandler.java
│  │  │          │              DefaultBeanDefinitionDocumentReader.java
│  │  │          │              DefaultDocumentLoader.java
│  │  │          │              DefaultNamespaceHandlerResolver.java
│  │  │          │              DocumentLoader.java
│  │  │          │              NamespaceHandler.java
│  │  │          │              NamespaceHandlerResolver.java
│  │  │          │              XmlBeanDefinitionReader.java
│  │  │          │              XmlBeanDefinitionStoreException.java
│  │  │          │              
│  │  │          ├─context
│  │  │          │  │  ApplicationContext.java
│  │  │          │  │  ApplicationContextAware.java
│  │  │          │  │  ApplicationEvent.java
│  │  │          │  │  ApplicationListener.java
│  │  │          │  │  ConfigurableApplicationContext.java
│  │  │          │  │  
│  │  │          │  ├─event
│  │  │          │  │      ApplicationEventMulticaster.java
│  │  │          │  │      ContextClosedEvent.java
│  │  │          │  │      ContextRefreshedEvent.java
│  │  │          │  │      SimpleApplicationEventMulticaster.java
│  │  │          │  │      
│  │  │          │  └─support
│  │  │          │          AbstractApplicationContext.java
│  │  │          │          AbstractRefreshableApplicationContext.java
│  │  │          │          AbstractXmlApplicationContext.java
│  │  │          │          ApplicationContextAwareProcessor.java
│  │  │          │          ClassPathXmlApplicationContext.java
│  │  │          │          FileSystemXmlApplicationContext.java
│  │  │          │          
│  │  │          ├─core
│  │  │          │  │  DefaultParameterNameDiscoverer.java
│  │  │          │  │  ParameterNameDiscoverer.java
│  │  │          │  │  
│  │  │          │  ├─convert
│  │  │          │  │  │  ConversionException.java
│  │  │          │  │  │  ConversionService.java
│  │  │          │  │  │  
│  │  │          │  │  ├─converter
│  │  │          │  │  │      ConditionalConverter.java
│  │  │          │  │  │      ConditionalGenericConverter.java
│  │  │          │  │  │      Converter.java
│  │  │          │  │  │      ConverterFactory.java
│  │  │          │  │  │      ConverterRegistry.java
│  │  │          │  │  │      GenericConverter.java
│  │  │          │  │  │      
│  │  │          │  │  └─support
│  │  │          │  │          DefaultConversionService.java
│  │  │          │  │          GenericConversionService.java
│  │  │          │  │          StringToBooleanConverter.java
│  │  │          │  │          StringToByteConverter.java
│  │  │          │  │          StringToCharacterConverter.java
│  │  │          │  │          StringToDateConverter.java
│  │  │          │  │          StringToDoubleConverter.java
│  │  │          │  │          StringToFloatConverter.java
│  │  │          │  │          StringToIntegerConverter.java
│  │  │          │  │          StringToLongConverter.java
│  │  │          │  │          StringToShortConverter.java
│  │  │          │  │          
│  │  │          │  ├─env
│  │  │          │  │      AbstractEnvironment.java
│  │  │          │  │      ConfigurableEnvironment.java
│  │  │          │  │      Environment.java
│  │  │          │  │      EnvironmentPropertySource.java
│  │  │          │  │      MapPropertySource.java
│  │  │          │  │      MutablePropertySources.java
│  │  │          │  │      Profile.java
│  │  │          │  │      PropertySource.java
│  │  │          │  │      PropertySources.java
│  │  │          │  │      StandardEnvironment.java
│  │  │          │  │      SystemEnvironmentPropertySource.java
│  │  │          │  │      SystemPropertySource.java
│  │  │          │  │      
│  │  │          │  └─io
│  │  │          │          ClassPathResource.java
│  │  │          │          DefaultResourceLoader.java
│  │  │          │          FileSystemResource.java
│  │  │          │          Resource.java
│  │  │          │          ResourceLoader.java
│  │  │          │          UrlResource.java
│  │  │          │          
│  │  │          ├─util
│  │  │          │      ClassUtils.java
│  │  │          │      
│  │  │          └─web
│  │  │              └─context
│  │  │                  └─request
│  │  │                          RequestScope.java
│  │  │                          SessionScope.java
│  │  │                          
│  │  └─resources
│  │      └─META-INF
│  │              spring.handlers

在实现ioc之前 需要先完全理解Bean对象是什么 根据代码随想录上面说的 Bean是由Spring ioc容器实例化并且管理的对象 在此之前 我也初步了解了bean在bean容器里的操作 bean在容器里面需要一个元数据来识别 在这个新项目当中 用了将bean的元数据转换成spring能够识别的BeanDefinetion对象 bean以及它们之间的关系都反应在配置元数据当中去

所以 我们需要先定义一个BeanDefinition对象 来定义Bean的信息

但是在定义这个对象之前 需要我们定义一些基本需要的属性 包括我们要管理的属性 bean的作用域 bean的异常处理定义


/**
 * Bean异常
 * @author shanshan
 * @date 2014-4-2 定义bean异常
 */
public class BeanException extends RuntimeException{
    public BeanException(String message){
        super(message);
    }
    public BeanException(String message,Throwable cause){
        super(message,cause);
    }
}
//定义非检查型异常 两种方式一种带消息 一种带消息+底层异常如:NullptrException
//消息和原因两种构造方式

这里定义了异常的两种方式

/**
 * 属性值模型
 * @author shanshan
 * @date 2014-4-2 定义bean异常
 */
public class PropertyValue {
    private final  String name;
    private final  Object value;

    public PropertyValue(String name, Object value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public Object getValue() {
        return value;
    }
}

定义属性 属性很简单 一个字段名和一个属性 spring容器会对其进行管理 如此定义比之前更方便了自定义以及管理


/**
 * 属性值集合
 * 放置管理属性
 * Created by shanshan on 2018/3/19.
 */


public class PropertyValues {
    private  final List<PropertyValue> propertyValueList=new ArrayList<>();
    /**
     * 添加属性值 放入一个属性对象*/
    public void addPropertyValue(PropertyValue propertyValue){
        this.propertyValueList.add(propertyValue);
    }
    /**
     * 获取属性值集合转成的数组*/
    public PropertyValue[] getPropertyValues(){
        return this.propertyValueList.toArray(new PropertyValue[0]);
    }
    /**
     * 根据属性名获取属性值*/
    public PropertyValue getPropertyValue(String propertyName){
        for (PropertyValue propertyValue:propertyValueList){
            if (propertyValue.getName().equals(propertyName)){
                return propertyValue;
            }
        }
        return null;
    }
}

当然一个bean不可能只有一个属性 还需要定义一个属性值集合

有了上面的基本定义好的东西 接下来需要定义bean的抽象了 根据spring的设计思想 我们的spring需要知道以下几个元素

  • bean的名字

  • bean的类型

  • bean的多个属性

  • bean的作用域

  • 初始化方法以及销毁方法

/**
 * bean的定义
 * @author dongms
 * @date 2020/07/09
 */
public class BeanDefinition {
    private Class<?> beanClass; //bean的类型
    private String beanClassName;
    private PropertyValues propertyValues; //bean的属性
    private String initMethodName; //初始化方法
    private String destroyMethodName; //销毁方法
    private boolean singleton = true; //是否单例
    private boolean prototype = false; //是否多例

    /**
     * 默认作用域
     */
    public static final String SCOPE_SINGLETON = "singleton";
    public static final String SCOPE_PROTOTYPE = "prototype";
}

由此 我们定义出了bean的抽象元数据 根据这些属性 spring就可以掌握并且管理bean了

public class test {
    @Test
    public void testBasicDefine(){
        PropertyValue pv = new PropertyValue("name","杜小猪");
        PropertyValue pv2 = new PropertyValue("active",false);
        PropertyValues pvs = new PropertyValues();
        pvs.addPropertyValue(pv);
        pvs.addPropertyValue(pv2);
        System.out.println(pvs);
        BeanDefinition bd = new BeanDefinition("com.dms.shanshan.beans.Person",pvs);
        System.out.println(bd.toString());
    }
}

进行测试查看输出

正常输出 并且能获取到信息 即说明已成功

综上我们实现了简单的bean定义模式

后记

仓库地址(不断更新):

https://gitee.com/du-mingshen1/hand-rubbing-spring-framework

全系列:杜明珅的手搓spring迷你框架系列

上一篇:手搓spring迷你框架之旅-04 Controller请求参数的实现

下一篇: