简单模拟Spring
生命不息,写作不止 继续踏上学习之路 , 学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德分享学习心得,欢迎指正,大家一起学习成长!上次已经学习了Java的设计模式 , 接下来就先来学习一下如何手写模拟简易的Spring,通过动手实践,才会更好的了解spring底层原理,今天就简单的模拟Spring容器是如何创建,bean又是如何注入的 。来看一下本次案例的spring类图
![【Spring系列】- 手写模拟Spring框架](http://pic.ikafan.com/imgp/L3Byb3h5L2h0dHBzL3VjYy5hbGljZG4uY29tL3BpYy9kZXZlbG9wZXItZWNvbG9neS82MjE2ZWY0OTFkYjg0NzE5ODY4M2M0M2QzZjA4MzdlMi5wbmc=.jpg)
文章插图
Spring容器模拟spring,首先就是需要一个容器 , 是Spring的核心,一切Spring bean都存储在Spring容器内,并由其通过IoC技术管理 。Spring容器也就是一个bean工厂(BeanFactory) 。应用中bean的实例化,获?。俚榷际怯烧飧鯾ean工厂管理的 。就像我们刚开始学习的时候接触的ApplicationContext,就是spring的容器 , 他就是为了完成容器的配置,初始化,管理bean的 。因此笔者自己创建了一个LydApplicationContext来模拟简单的spring容器 。
开始使用首先通过new LydApplicationContext(AppConfig.class)实例化对象,在通过applicationContext.getBean("userService")去获得bean对象 。然而在容器的初始化可是做了许多的事情 , 包括扫描、实例化bean等等操作 。初始容器创建:
public class LydApplicationContext { private Class configClass; public LydApplicationContext(Class configClass) { // 构造方法 this.configClass = configClass; }}Spring扫描底层实现Spring容器建好之后我们就需要通过配置文件的注解获取扫描路径,我们需要获取所有的bean,并且需要实例对象 。在此我们需要一个配置文件,就是使用new LydApplicationContext(AppConfig.class) 实例携带的配置类,当然这里有好多的形式,也可以是通过xml文件来处理 。
配置文件AppConfig.java这个就是为了提供扫描的包路径的 , 不做任何操作,所以不需要其他代码 。
@ComponentScan("com.lyd.service") // 扫描路径,扫描这个包下的public class AppConfig {}通过注解存放这个包路径 , 在后面可以通过这个注解来获取包路径,所以就需要我们创建一个ComponentScan注解 。
编写ComponentScan注解这个注解是用来spring容器扫描包为之提供包路径 。
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface ComponentScan { // 指定扫描路径 String value() default "";}编写Component注解在Spring中,通过Component注解将bean注入Spring容器中,这里我们也采用高这个注解 。
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Component { String value() default "";}获取包路径既然已经通过注解将包路径存在配置类中,接下来就可以通过这个注解来得到 。但是,在这里需要注意的是,我们扫描的并非是java源文件,而是编译后的class文件 。我们需要在LydApplicationContext的构造方法中去实现 。首先 , 我们需要通过isAnnotationPresent方法先判断是否存在ComponentScan注解 , 在通过类的getAnnotation方法来得到注解 。这样就可以直接得到注解上的值 。这个值就是我们写入的包路径,注意,这里的路径是com.lyd.service,而我们需要用替换方法将'.'替换成'/',因为在后面获取资源路径的时候 , 用的是com/lyd/service这种形式,也就是相对路径 。接下来需要获取资源路径 , 这个时候就需要用到类加载器LydApplicationContext.class.getClassLoader() , 类加载器中有一个getResource(path)方法,这个可以根据传入的路径获取相应的资源,最后是能够拼出我们需要的绝对路径 。
if (configClass.isAnnotationPresent(ComponentScan.class)) { ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class); // 1.1 扫描路径:只是个包名,扫描的是java的class文件,而并非源文件,com.lyd.service String path = componentScanAnnotation.value(); // 1.2 将路径文件替换成/的形式 path = path.replace(".","/"); // 1.3 通过类加载器获取资源路径 ClassLoader classLoader = LydApplicationContext.class.getClassLoader(); URL resource = classLoader.getResource(path); // 1.4 转成文件形式,主要是为了获取他的绝对地址 File file = new File(resource.getFile()); System.out.println(file);}
推荐阅读
- 【ASP.NET Core】MVC控制器的各种自定义:应用程序约定的接口与模型
- 基础版 【网络】内网穿透方案&FRP内网穿透实战
- FGO日服七周年礼装自选哪个好
- 蚂蚁庄园今日答题答案是什么
- iqooneo5是什么屏幕_iqooneo5屏幕尺寸参数
- 原神如何去雷神的岛屿(原神如何上雷神岛)
- 一次SpringBoot版本升级,引发的血案
- 中 学习ASP.NET Core Blazor编程系列十——路由
- 小米11和vivox60哪个好_小米11和vivox60参数对比
- 苹果13mini屏幕多大尺寸_苹果13mini屏幕尺寸