简单实现Spring容器(一)

阶段1:

 编写自己的Spring容器,实现扫描包,得到bean的class对象.

思路:

使用 ElfSpringConfig.java 替代beans.xml文件作为配置文件,从中获取到:
1.扫描包,得到bean的class对象.
2.排除包下不是bean的

在这里插入图片描述
在这里插入图片描述

1.容器文件 ElfSpringApplicationContext.java 核心!!!

package com.elf.spring.ioc;import com.elf.spring.annotation.*;import java.io.File;
import java.net.URL;/*** @author 45~* @version 1.0*/
public class ElfSpringApplicationContext {//第一步,扫描包,得到bean的class对象,排除包下不是bean的,因此还没有放到容器中//因为现在写的spring容器比原先的基于注解的,要更加完善,所以不会直接把它放在ConcurrentHashMapprivate Class configClass;//构造器public ElfSpringApplicationContext(Class configClass) {this.configClass = configClass;/**获取要扫描的包:1.先得到ElfSpringConfig配置的 @ComponentScan(value= "com.elf.spring.component")2.通过 @ComponentScan的value => 即要扫描的包 **/ComponentScan componentScan =(ComponentScan) this.configClass.getDeclaredAnnotation(ComponentScan.class);String path = componentScan.value();System.out.println("要扫描的包path=" + path);/*** 得到要扫描包下的所有资源(类.class)* 1.得到类的加载器 -> APP类加载器是可以拿到 target目录下的classes所有文件的* 2.通过类的加载器获取到要扫描的包的资源url => 类似一个路径* 3.将要加载的资源(.class)路径下的文件进行遍历 => io*/ClassLoader classLoader = ElfSpringApplicationContext.class.getClassLoader();path = path.replace(".", "/"); // 把.替换成 /URL resource = classLoader.getResource(path);System.out.println("resource=" + resource);File file = new File(resource.getFile());if (file.isDirectory()) {File[] files = file.listFiles();for (File f : files) { //把所有的文件都取出来System.out.println("============================");System.out.println("f.getAbsolutePath()=" + f.getAbsolutePath());String fileAbsolutePath = f.getAbsolutePath();//到target的classes目录下了//这里只处理.class文件if (fileAbsolutePath.endsWith(".class")) {//1.获取类名String className = fileAbsolutePath.substring(fileAbsolutePath.lastIndexOf("\\") + 1,fileAbsolutePath.indexOf(".class"));//2.获取类的完整路径(全类名)String classFullName = path.replace("/", ".") + "." + className;System.out.println("classFullName=" + classFullName);//3.判断该类是否需要注入,就看是不是有注解@Component @Service @Contoller @Re....try {Class<?> clazz = classLoader.loadClass(classFullName);if (clazz.isAnnotationPresent(Component.class) ||clazz.isAnnotationPresent(Controller.class) ||clazz.isAnnotationPresent(Service.class) ||clazz.isAnnotationPresent(Repository.class)) {//演示机制//如果该类使用了@Component注解,说明是一个Spring beanSystem.out.println("这是一个Spring bean=" + clazz + " 类名=" + className);}
//                                Component component = clazz.getDeclaredAnnotation(Component.class);
//                                String id = component.value();
//                                if (!"".endsWith(id)) {
//                                    className = id;//替换
//                                }else {//如果该类没有使用了@Component注解,说明是一个Spring beanSystem.out.println("这不是一个Spring bean" + clazz + " 类名=" + className);}
//                            Class<?> Class = Class.forName(classFullName);
//                            Object instance = Class.newInstance();
//                            ioc.put(StringUtils.uncapitalize(className), instance);} catch (Exception e) {e.printStackTrace();}}}//遍历文件for循环结束System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");}}//构造器结束//编写放法返回容器中的对象public Object getBean(String name) {return null;}
}

2.AppMain.java

package com.elf.spring;
import com.elf.spring.ioc.ElfSpringApplicationContext;
import com.elf.spring.ioc.ElfSpringConfig;/*** @author 45~* @version 1.0*/
public class AppMain {public static void main(String[] args) {//把容器创建起来,在创建的时候传入了配置类的class类型/class对象//传进去后会根据自己写的容器机制 进行解析ElfSpringApplicationContext elfSpringApplicationContext =new ElfSpringApplicationContext(ElfSpringConfig.class);}
}

3.配置文件 ElfSpringConfig.java

package com.elf.spring.ioc;
import com.elf.spring.annotation.ComponentScan;/*** @author 45~* @version 1.0* 这是一个配置类,作用类似于原生spring的beans.xml容器配置文件*/
@ComponentScan(value= "com.elf.spring.component")
public class ElfSpringConfig {}

4.component包下的类car / monsterDao / monsterService

package com.elf.spring.component;/*** @author 45~* @version 1.0*/
public class car {
}
package com.elf.spring.component;
import com.elf.spring.annotation.Component;
/*** @author 45~* @version 1.0* 写第二个类是因为要有两个类才能做依赖注入*/
@Component(value = "monsterDao")
public class MonsterDao {
}
package com.elf.spring.component;
import com.elf.spring.annotation.Component;
/*** @author 45~* @version 1.0* 说明 MonsterService 是一个Servic*/
@Component //把MonsterService注入到我们自己的spring容器中
public class MonsterService {}

5.annotation包下的一堆自定义注解 ComponentScan + 经典4

package com.elf.spring.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author 45~* @version 1.0*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {String value() default "";
}
package com.elf.spring.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author 45~* @version 1.0*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {//通过value可以给注入的bean/对象指定名字String value() default "";
}
package com.elf.spring.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author 45~* @version 1.0*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {//通过value可以给注入的bean/对象指定名字String value() default "";
}
package com.elf.spring.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author 45~* @version 1.0*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Repository {//通过value可以给注入的bean/对象指定名字String value() default "";
}
package com.elf.spring.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author 45~* @version 1.0*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {//通过value可以给注入的bean/对象指定名字String value() default "";
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/205755.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构练习——素数统计

题目描述 大家都知道素数的概念&#xff0c;如果1个数只有1和它自己两个因数的话&#xff0c;则这个数被称之为素数&#xff0c;也叫做质数&#xff0c;因此最小的素数是2。 现在想问你&#xff0c;给定2个正整数n和m&#xff0c;从n到m&#xff08;含n、m&#xff09;的所有素…

vuepress-----13、分割config

13、分割config config.js const headConfig require(./config/headConfig); const pluginsConfig require(./config/pluginsConfig); const themeConfig require(./config/themeConfig)module.exports {title: "小邵子",description: 小邵子的个人笔记,head: he…

微信小程序 - 文件工具类 fileUtil.js

微信小程序 - 文件工具类 fileUtil.js const fs wx.getFileSystemManager();/*** 选择媒体附魔的ZIP* param {object} options */ function chooseMediaZip(options {}){const defaultOptions { count: 9, mediaType: [image]};let params {...defaultOptions, ...options}…

GO设计模式——14、代理模式(结构型)

目录 代理模式&#xff08;Proxy Pattern&#xff09; 代理模式的核心角色&#xff1a; 优缺点 使用场景 注意事项 代码实现 代理模式&#xff08;Proxy Pattern&#xff09; 代理模式&#xff08;Proxy Pattern&#xff09;通过引入代理对象来控制对真实对象的访问。 代…

Mybatis一级缓存与二级缓存

一、简介 数据库接收到sql语句后&#xff0c;需要词法/语法解析&#xff0c;优化sql语句&#xff0c;制定执行计划。多数情况下&#xff0c;相同的sql语句可能只是传入参数不同&#xff08;如where条件后的值不同...&#xff09;。 如果每次都需要经过上面的 词法/语法解析、语…

java基础之异常处理

1、概念 异常是程序中的一些错误&#xff0c;但并不是所有的错误都是异常&#xff0c;并且错误有时候是可以避免的。 2、异常发生的原因 用户输入了非法数据。要打开的文件不存在。网络通信时连接中断&#xff0c;或者JVM内存溢出。 3、三种类型的异常 检查性异常&#xff1a;…

Unity UGUI TextMeshPro实现输入中文和表情包(Emoji)表情

目录 实现中文显示 准备工作 1、打开Window——TextMeshPro——FontAssetCreator 2、把字体文件放入SourceFont中 3、把CharacterSet改为Characters from File 4、把字体库文件放入Characters File 5、设置好参数点击Generate Font Atlas等待完成后保存 6、把生成后保存…

科普小知识-3D 打印是什么?

3D 打印是什么&#xff1f;作为近年来备受关注的前沿科技&#xff0c;3D 打印技术正在不断改变着制造业、医疗领域、艺术设计等多个领域的面貌。其又被称为增材制造&#xff0c;是一种通过电脑设计&#xff0c;逐层堆叠材料来创建三维物体的技术。 3D 打印的基本原理 3D 打印…

【Ajax】发送get请求获取接口数据

编写html实现通过Ajax发送get请求并获取数据 代码实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title…

LinuxBasicsForHackers笔记 -- 管理用户环境变量

查看和修改环境变量 env – 您可以通过从任何目录在终端中输入 env 来查看所有默认环境变量。环境变量的名称始终为大写&#xff0c;如 HOME、PATH、SHELL 等。 查看所有环境变量 set – 查看所有环境变量&#xff0c;包括 shell 变量、局部变量和 shell 函数&#xff08;例…

2. PyTorch——Tensor和Numpy

2.1Tensor和Numpy Tensor和Numpy数组之间具有很高的相似性&#xff0c;彼此之间的互操作也非常简单高效。需要注意的是&#xff0c;Numpy和Tensor共享内存。由于Numpy历史悠久&#xff0c;支持丰富的操作&#xff0c;所以当遇到Tensor不支持的操作时&#xff0c;可先转成Numpy…

conda配置不同版本的python及依赖库--conda conda conda

一、conda介绍 Conda 是一个开源的软件包管理系统和环境管理系统&#xff0c;用于安装多个不同版本的软件包及其依赖关系&#xff0c;并在它们之间轻松切换。 Conda 是为 Python 程序创建的&#xff0c;适用于 Linux&#xff0c;OS X 和Windows Conda可以构建不同的环境&#…

【计算机网络学习之路】HTTP响应报文Cookie原理

目录 HTTP响应报文格式 一. 状态行 状态码与状态码描述 二. 响应头 Cookie原理 一. 前因 二. Cookie的状态管理 结束语 HTTP响应报文格式 HTTP响应报文分为四部分 状态行&#xff1a;包含三部分&#xff1a;协议版本&#xff0c;状态码&#xff0c;状态码描述响应头&a…

企业计算机服务器中了mallox勒索病毒如何处理,Mallox勒索病毒解密

随着计算机技术的不断发展&#xff0c;越来越多的企业利用网络来提高工作效率&#xff0c;但随之而来的网络安全威胁也在不断增加&#xff0c;各种勒索病毒种类不断增加&#xff0c;给企业的数据安全带来严重的威胁&#xff0c;影响企业的生产业务开展。近期&#xff0c;云天数…

什么是css初始化

什么是css初始化 CSS初始化是指重设浏览器的样式。 因为浏览器的兼容问题&#xff0c;不同浏览器对有些标签的默认值是不同的&#xff0c;如果没对CSS初始化往往会出现浏览器之间的页面显示差异。 每次新开发网站或新网页时候通过初始化CSS样式的属性&#xff0c;为我们将用…

opencv的图像直方图处理

1 opencv的直方图 1.1 什么是直方图 直方图是对数据进行统计的一种方法&#xff0c;用于显示数据中各个数值或数值范围的分布情况。它将数据划分为一系列的区间&#xff08;也称为“箱子”或“bin”&#xff09;&#xff0c;然后统计每个区间中数据出现的频次&#xff08;或频…

用心整理的免费API集合

快递物流订阅与推送&#xff08;含物流轨迹&#xff09;&#xff1a;【物流订阅与推送、H5物流轨迹、单号识别】支持单号的订阅与推送&#xff0c;订阅国内物流信息&#xff0c;当信息有变化时&#xff0c;推送到您的回调地址。地图轨迹支持在地图中展示包裹运输轨迹。包括顺丰…

Flink-源算子-读取数据的几种方式

Flink可以从各种来源获取数据&#xff0c;然后构建DataStream进行转换处理。一般将数据的输入来源称为数据源&#xff08;data source&#xff09;&#xff0c;而读取数据的算子就是源算子&#xff08;source operator&#xff09;。所以&#xff0c;source就是我们整个处理程序…

微服务2 Docker学习 P42-P60

Docker学习视频https://www.bilibili.com/video/BV1LQ4y127n4?p42&vd_source8665d6da33d4e2277ca40f03210fe53a 文档资料: 链接&#xff1a;https://pan.baidu.com/s/1P_Ag1BYiPaF52EI19A0YRw?pwdd03r 提取码&#xff1a;d03r Docker 其他笔记 服务器容器化-docker(全…

CSS3 属性: transition过渡 与 transform动画

CSS3 提供了很多强大的功能&#xff0c;使开发人员可以创建更加吸引人的视觉效果&#xff0c;而不需要依赖于 JavaScript 或 Flash。其中&#xff0c;transition 和 transform 是两个常用的属性&#xff0c;它们分别用于创建平滑的过渡效果和元素的变形效果。下面我们将详细介绍…