# cuckooing-spring **Repository Path**: cuckooing/cuckooing-spring ## Basic Information - **Project Name**: cuckooing-spring - **Description**: Spring Demo - **Primary Language**: Unknown - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-04-05 - **Last Updated**: 2024-04-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 参考Spring底层原理后写的一个 Spring Demo。 主要实现了 IOC 和 AOP 功能,大部分类名都和 Spring 中的类名一致。 对 AOP 中的主要接口做了抽象,方便扩展。简单起见,和 Spring 的接口设计略有不同。 ## IOC ### Bean生命周期 - 实现@ComponentScan组件扫描,Bean 生命周期(扫描、依赖注入、初始化、销毁) - 包括:Bean后处理器 [BeanPostProcessor](src/com/cuckooing/spring/interfaces/BeanPostProcessor.java) 的调用、各种 Aware 接口回调 - 实现@Autowired注解,通过byName从容器中查找依赖,达到依赖注入效果 ### 循环依赖 - 实现三级缓存,解决属性注入和 set方法注入的循环依赖问题,也解决了涉及注入代理对象的循环依赖问题。 - 实现@Lazy 注解、[ObjectFactory](src/com/cuckooing/spring/interfaces/ObjectFactory.java) ,解决构造方法注入的循环依赖问题。 - 两边相互依赖的 Bean 必须至少其中一个是单例Bean,才能解决循环依赖问题。 - 采用构造方法注入,单例、多例都行。 - 做了循环引用检测,发现循环引用时抛出异常,而不是无限递归爆栈。 **出现循环依赖时会抛出异常的原因** - 使用「属性注入或 set 方法注入」两边相互依赖的 Bean 都是多例 bean。 - 使用构造方法注入没加 @Lazy、ObjectFactory 推迟注入 Bean。 **解决方案** - 多实例的Setter注入导致的循环依赖,需要把Bean改成单例 - 构造器注入导致的循环依赖,可以通过@Lazy注解 - @Dependson导致的循环依赖,找到注解循环依赖的地方,迫使它不循环依赖 - 单例的代理对象Setter注入导致的循环依赖 - - 可以使用@Lazy注解 - 或者使用@DependsOn注解指定加载先后关系 ### 简化的容器refresh流程 - 收集 BeanDefinition,根据 @ComponentScan 的包路径扫描加了 @Component 注解的类,放入beanDefinitionMap。 - 向容器中注册基本的 Bean 后置处理器(BeanPostProcessor)BeanDefinition,创建beanDefinitionMap中所有Bean的后置处理器,放入容器 singletonObjects (单例池)中,添加到 beanPostProcessorList。 - 初始化所有单例 bean。 - 容器类的实现:CuckooingApplicationContext。 ## AOP ### 通知注解 - 完成了 5 种通知类型([@Before](src/com/cuckooing/spring/aop/anno/Before.java)、[@AfterReturning](src/com/cuckooing/spring/aop/anno/AfterReturning.java)、[@After](src/com/cuckooing/spring/aop/anno/After.java)、[@AfterThrowing](src/com/cuckooing/spring/aop/anno/AfterThrowing.java)、[@Around](src/com/cuckooing/spring/aop/anno/Around.java))的解析,对符合切点的目标对象进行代理增强。应用在目标方法上的多个通知会链式调用执行,且实现了通知的调用顺序控制(对 [Advisor](src/com/cuckooing/spring/aop/advisor/Advisor.java) 切面排序)。 ### 实现方式 - 切点表达式的解析使用 ((String)(expression)).contains(className) 进行简单地判断,判断通过表示此切面可以应用在这个 class 上,能对这个 class 中所有方法进行增强。 - AOP 功能的实现在 com.cuckooing.spring.aop 包下,通过 Bean 后置处理器 [AnnotationAwareAspectJAutoProxyCreator](src/com/cuckooing/spring/aop/AnnotationAwareAspectJAutoProxyCreator.java) 对符合切点的目标对象进行代理增强。如果发生了循环依赖要在依赖注入阶段提前创建代理,此 Bean 后处理器使用缓存避免了代理对象的重复创建。 - 可以使用 [AopContext](src/com/cuckooing/spring/aop/proxy/AopContext.java) 获取当前线程正在运行的 AOP 代理对象。 ## 涉及的设计模式 - 代理模式(JDK 生成动态代理对象) - 责任链模式(通知的链式调用) - 单例模式(比较器 OrderComparator) - 适配器模式(适配各种销毁方法的调用) - 工厂模式(ObjectFactory) **功能测试 Demo:**在 com.cuckooing.test 包下