# ht-spring **Repository Path**: htao666/ht-spring ## Basic Information - **Project Name**: ht-spring - **Description**: 自己造轮子 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-02-27 - **Last Updated**: 2024-04-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 第一个版本的Spring IOC ![1709105785580](img/1709105785580.png) 当前的 ClassPathXmlApplicationContext 在实例化的过程中做了三件事: **1.XmlBeanDefinitionReader读取 xml资源** 读取Resource 的具体实现 为classpathXmlResource 这个类间接继承了一个接口 extends Iterator 更方便XmlBeanDefinitionReader的读取 **2.加载解析的内容,构建 BeanDefinition** 这部分也是在XmlBeanDefinitionReader中实现的,之后在读取 BeanDefinition 的配置信息,实例化 Bean,然后把它注入到 BeanFactory 容器中。 # IOC使用的设计模式 工厂设计模式:Spring使用工厂模式通过BeanFactory和ApplicationContext创建bean对象。 单例设计模式:Spring中的bean默认都是单例的。 观察者模式:Spring事件驱动模型就是观察者模式很经典的一个应用。 # 小记观察者模式 在mini-spring中实现了事件监听机制 实质就是发布者维护一个监听者的列表 事件ApplicationEvent需要继承一个对象 java.util.EventObject 监听者ApplicationListener需要实现一个接口java.util.EventListener 发布者就是遍历由监听者组成的list 然后进行listener.onApplicationEvent(event);函数调用 发布订阅有点类似于MQ # 第一个版本的AOP是如何实现的呢 ![1709294833513](img/1709294833513.png) 我们可以发现action是一个代理bean 这个类实现了FactoryBean的接口 后续通过判断bean是否实现了了FactoryBean的接口就可以对代理bean进行特殊的处理 FactoryBean的内部有个getObject的函数 在ProxyFactoryBean中对其进行了重写 当调用getObject函数时,实际上是使用JDK代理生成了一个代理后的对象返回了 # 第二个版本AOP是如何实现的 第一个版本中最大的缺点在于生成代理时,代理需要的操作不是自定义的,需要把这个接口自定义 首先,这也需要是一个bean ![1709350115241](img/1709350115241.png) ![1709350132692](img/1709350132692.png) 这个bean会被注入到代理的bean中 那么实际上此时代理就拿到了 被代理对象 以及代理操作 后面步骤为: 1)在抽象bean工厂中 将BeanFactory给到代理对象 方便其获取内部interceptorName 的属性 对应的bean 2)判断 如果一个bean属于FactoryBean 那么则要返回一个包装后的代理对象 执行factoryBean.getObject(); 3)factoryBean而这个bean实际上就是ProxyFactoryBean 4)内部会先进行初始化 比如根据interceptorName 获取对应的bean 这个使用advice接收 判断这个属于哪个子接口 然后强转为相应的advice 根据类型后 交给相应的拦截器 并将拦截器给advisor advisor将会作为参数传入代理的实现类 5)然后就是创建代理:getSingletonInstance 而JDK中的invoke是执行 拦截器的invoke 然后不同的拦截器将会实现不同的invoke 至于添加的内容 是在**advice中实现的** # 第三个版本的AOP ![1709369715301](img/1709369715301.png) 这个版本主要是实现了任意的函数进行匹配 ![1709381021680](img/1709381021680.png) advisor决定了 通知 和 切点 通知决定于是在方法执行的哪一步来完成什么事 而 切点决定了是那些方法来完成 AOP增强 但是写到这里还有一个问题 就是 当前的代理只能给单个bean进行代理 实际上也需要一个类似于上面的匹配方式 解决方案是 在初始化函数前后的后置处理器中 对Bean进行判断 如果需要增强 符合条件 就使用一个代理类来替换之前的bean # 可以优化的点 1)通过类型返回bean:思路只需要在getBean的地方进行重载,需要遍历一遍是否已经有了 否则就遍历beanDefinition看看是否已经有这个bean信息 没有就返回null ClassPathXmlApplicationContext ``` @Override void registerBeanPostProcessors(ConfigurableListableBeanFactory bf) { this.beanFactory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor()); } ``` 2)三级缓存解决循环依赖问题 目前相当于只是使用了二级缓存 三级缓存是指的是 一开始不是存 毛坯对象 而是存lambda表达式(beanname BeanDefinition bean) 只有真正需要使用到二级缓存的对象并且不存在时 才会从三级缓存中拿取 然后进行创建 为什么整个三级缓存呢? 主要还是为了解决AOP的动态代理问题 # 第一个版本的JdbcTemplate 是如何完成的呢 首先通过 模版化的设计思想 将固定部分保存 将特殊的地方给抽取出来 目前在使用的时候 只需要注入后,将相应的sql语句和参数 以及相应的操作传入即可 操作时使用一个接口 实现 回调方法来完成的 目前存在的问题 在JdbcTemplate中是不需要实现这这个回调方法的