# litespring **Repository Path**: zlray/litespring ## Basic Information - **Project Name**: litespring - **Description**: litespring - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2020-11-01 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 改代码位置在:https://github.com/onlyliuxin/litespring 我自己的代码库:https://gitee.com/baishui0212/litespring (1)手写spring基本的 IOC 和AOP的相关功能点 (2)一个阶段的内容会按照分支的形式进行提交 (3)会把每个阶段的大概内容记录下来的 (4)类图在 【litespring.drawio】 中 ======================= 第一个阶段 ============================= 【主要内容:BeanFactory,BeanDefinition,Resource,SingletonBeanRegistry】 version-1 实现的功能点: BeanDefiniton:bean的定义信息 ======》 GenericBeanDefinition BeanFactory的接口,以及对应的实现类 ======》 DefaultBeanFactory (1)使用构造器传入配置文件信息 (2)获取对应的classLoader,获取该配置文件的流信息 (3)DOM解析 (4)保存bean的定义信息,只是定义,并没有真正的实例化 getBean()方法 (1)从beanMap中获取bean的定义信息,就是对应的classpath,test.service.BaishuiService (2)获取当前的classLoader进行bean的实例化 (3)返回bean 不足的地方:DefaultBeanFactory中包含了很多的功能点,比如,读取文件,解析文件,保存bean信息等 经验点: (1)classUtils 工具类使用abstract,防止被其他程序实例化,目的:工具类静态方法的调用 (2)单一职责原则 version-2 单一职责原则: 职责:是引起变化的原因 - 如果多余一个的动机去改变这个类,这个类就具备多个职责 SRP:对于一个类而言,应该只有一个引起他变化的原因 BeanFactory的拆分 (1)配置文件读取和解析 -> XmlBeanDefinitionReader 和 BeanDefinitionRegistry 引入Application和ClassPathApplicationContext version-2-1 增加 Resource ClassPathResource FileSystemResource:负责创建出不同的流 Resource 的作用就是持久不同的InputStream 进行loadBeanDefinitions的时候,只需要传入Resource即可 引入FileSystemXmlApplicationContext version-2-2 模版方法 引入 AbstractApplicationContext,获取不同的Resource FileSystemXmlApplicationContext 和 ClassPathApplicationContext version-2-3 增加 ConfigurableBeanFactory :classloader的设置以及获取 version-2-4 处理scope的问题 增加 SingletonBeanRegistry 接口 对应实现:DefaultSingletonBeanRegistry DefaultBeanFactory作用: (1)承担 ConfigurableBeanFactory (2)注册 bean 的定义信息 BeanDefinitionRegistry (3)生成并保存单例bean的作用 ======================= 第二个阶段 ============================= 【setter的注入,以及增加了xml文件对setter的描述的类,比如 TODO 】 TDD:BaishuiV2Service,Car,House,litespring-v2.xml 引入 PropertyValue{ private String name; private Object value:-》 保存的是各种bean的Reference,待后续 TypeConverter 进行解析 private Object convertedValue; -> 实际存放的ref的 实例对象 } RuntimeBeanReference TypedStringValue xml中的property的顺序问题 BeanDefinitionValueResolver: 解析PropertyValue中的value中,转换成真正的实例对象, 需要持有BeanFactory中实例 --- 增加了log 拆分了createBean方法:instantiateBean 和 populateBean 先进行实例化,而后进行setter进行注入属性 引入 BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); - JDK 引入类型转换:TypeConverter SimpleTypeConverter PropertyEditor[java]--TODO ======================= 第三个阶段 ============================= 【构造函数,增加了】 BeanDefinition中增加了属性【ConstructorArgument】来进行描述 ValueHolder 只在 ConstructorArgument 中使用,高内聚,低耦合 静态内部类:ValueHolder{ name type value } ConstructorArgument Collections.unmodifiableList(this.argumentValues) -- 返回不可修改集合 疑问点: 存在多个构造器,使用哪个构造器进行初始化呢??? ======================= 第四个阶段 ============================= 【实现Spring的注解】 具体步骤: (1)读取XML文件 (2)对指定的package包进行扫描,标记为 @Component,并转换为 beanDefinition 2.1 把一个package包下面的class变成 Resource 引入 PackageResourceLoader 2.2 使用ASM读取Resource中的注解 2.3 创建BeanDefiniton (3)通过Beanfinition创建bean的实例,根据注解进行注入 ======= ASM ======== - 一个可以操作java字节码的框架 - 可以读取和修改class中的字节码 工作模式:Visitor模式 Class Reader Class Visitor Class Writer ======================= 第五个阶段 ============================= 如何实现AOP (1)编译期 “增强”:AspectJ (2)运行期动态生成类 -> 代理类 CGLib JDK的动态代理 专业术语: Joint Point:代表一个方法的执行点 PointCut:匹配joint point的断言 -> 本质就是execution() Advice:拦截器 Before Advice: 步骤: (1)PointCut:给定一个类的方法,是否和表达式匹配 PointCut MethodMatcher -> AspectJExpressionPointCut为具体实现 (2)定位Method 需要通过类的名称("tx")和方法名("start")定位到这个method,然后通过反射进行调用 MethodLocatingFactory (3)ReflectiveMethodInvocation 目标:拦截器能够以正确的顺序执行 aop aliance 需要完成的功能: (1)根据bean的名称和方法,获取method对象 (2)给定一个类的方法,判断该方法是否符合pointcut的表达式 (3)实现了Before,AfterReturning,AfterThrowing等Advice (4)实现了Advice按次序执行 - ReflectiveMethodInvocation (5)给定一个AOPConfig,使用CGLib生成一个对象的代理 (6)从XML中创建 BeanDefiniton ======================= 第六个阶段 ============================= ================================================================= 访问class的时候,我们实现了vistor方法,进行class以及注解中的信息的保存 DefaultBeanFactory{ - classLoader{} - beanDefinitionMap{ GenericBeanDefiniton { id beanClassName singleton prototype scope beanClass propertyValues{ name value converted convertedValue } constructorArgument{ List } isSynthetic } SannedGenricBeandefinition { metadata{ annotationSet attributeMap className isInterFace isAbstract isFinal superClassName interfaces api cv } } } - beanDefinitionProcessors{ beanPostProcessor{ beanFactory requiredParameterName requiredParameterValue autowireAnnotationTypes } } -singletonObjects{ } }