当前位置: 首页 > 后端技术 > Java

手写模拟Spring-Bean的创建和获取底层原理

时间:2023-04-01 16:53:46 Java

作者:京东物流张定远1简介大家好,相信大家对Spring的底层原理都有一定的了解。在代码中手动实现一个简单版的Spring,促进对Spring架构的更深入的理解,对Spring的常用功能进行手写模拟。2启动Spring以创建和获取bean。让我们来实现这些功能。首先,我们创建JdApplicationContext类作为Spring的启动类,实现bean的加载和获取功能。UserService和OrderService类是Bean的实现类,前两个类的实现是通过JdApplicationContext类中的getBean方法获取的。App是启动测试类。AppConfig是启动配置类。注:以下代码会顺着内容一步步完成。首先创建App类作为测试Spring功能的入口。通过初始化JdApplicationContext类,动态加载bean实例。通过getBean方法获取bean实例。创建一个JdApplicationContext类,提供获取Bean实例的方法,通过构造函数动态初始化bean实例。3扫描类路径并缓存BeanDefinition数据。JdApplicationContext类初始化时,通过AppConfig配置类获取该类的扫描路径。在扫描路径下,找到需要创建bean的类,通过标注Component注解的类来识别需要创建的bean。将Component注解标识的类封装成一个BeanDefinition,然后缓存在beanDefinitionMap的内存中。在上面的代码中,我们发现在创建BeanDefinition类时,封装了类class、beanName、scope这三个主要属性。用于创建bean时,提供类类进行初始化和属性注入,创建单例类或原型类提供数据基础。4初始化Bean和依赖注入接下来,上述扫描操作完成后,将所有需要初始化的bean数据存储到beanDefinitionMap中。我们只需要遍历beanDefinitionMap数据,将属性一一初始化和注入即可。上面代码中,在初始化bean时,从beanDefinition中获取要初始化的类,通过反射机制进行无参初始化。初始化完成后,对带有Autowired注解的属性进行依赖注入。当Autowired注解不传递value值时,默认使用属性名作为beanName,通过getBean方法获取bean实例。getBean方法会通过beanName从beanDefinitionMap中获取beanDefinition数据。通过beanDefinition确认bean是单例原型类。如果是原型类,直接调用createBean方法初始化bean。如果是单例类,先从singletonBeanMap缓存中获取bean实例。如果没有,调用createBean方法获取bean实例,将创建的bean实例缓存到singletonBeanMap缓存中。至此,在上述功能中,简单版的依赖注入就已经实现了。同时我们注意到UserService和OrderService可能存在循环依赖问题。这里怎么解决?问题代码如下:上图是循环依赖问题代码导致的异常。反复创建bean进入死循环。在初始化bean和属性注入之间,我们可以加一个二级缓存作为突破口,解决死循环问题。userService初始化后,需要注入orderService,通过getBean方法获取。因为orderService不在singletonBeanMap缓存中,所以也需要初始化注入到userService属性中。同时userService还在初始化过程中,无法缓存到singletonBeanMap缓存中。导致彼此循环等待属性的注入。要解决这个问题,我们只需要在初始化过程中在creatingBeanMap中设置缓存即可。userService初始化后,在进行属性注入之前,缓存在creatingBeanMap中。userService需要的orderService属性在创建bean实例的过程中优先从creatingBeanMap缓存中获取。UserService实例,完成bean实例的创建过程。orderService完成bean实例创建后,userService也相应完成实例创建。5实现InitializingBean接口在createBean的过程中,我们可以对外提供初始化扩展接口InitializingBean接口。只要实现了这个接口,我们就可以实现bean初始化的扩展功能。![]6实现BeanPostProcessor接口模拟AOP首先创建BeanPostProcessor接口,创建BeanPostProcessor接口实现类作为所有bean实例的对外扩展接口,模拟AOP功能,为aspect指定userService类。扫描类时,将实现了BeanPostProcessor接口的类缓存到beanPostProcessorList中。通过上面的扫描,beanPostProcessorList已经缓存了所有的BeanPostProcessor实现类。createBean时,对创建的bean实例进行预处理和扩展。上面代码的实现效果如下:源码:https://3.cn/109Aj-Zok7总结在上面的讲解中,我们简单的实现了Spring的底层原理,通过类扫描和注解识别判断,??定义和beanDefinition的缓存。通过反射和代理创建和扩展bean实例。相信大家也能看出在实现过程中有很多需要改进的地方,还有很多Spring的其他功能可以继续扩展。比如扩展beanDefinition的注册,Bean工厂的引入,懒加载等。

最新推荐
猜你喜欢