本人突然特别感兴趣于轮子开发 然现在很多公司对spring源码都有理解考察 并且学校只教简单的spring框架应用 知其然而不知其所以然 故本人将会借助深度思考ai加上自己的理解 完成我第一个轮子开发之spring框架的开发 起名为Shanshan框架
本篇将会实现最简单的自定义component注解+beanFactory进行测试
核心思想
首先整理一下简单的基础思想 spring最基本的思想是容器化思想 也就是借助component注解来将类放在容器BeanFactory中进行管理 BeanFactory作为核心容器类 需要对项目包结构进行扫描 然后将带有component注解的类给利用反射给加载进容器当中 从而实现管理
那么开始新建项目
首先新建一个maven项目 项目结构为:
(cmd命令tree /f . >tr.txt 生成)
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─dms
│ │ │ └─shanshan
│ │ │ │ Main.java
│ │ │ │ test.java
│ │ │ │
│ │ │ └─core
│ │ │ │ BeanFactory.java
│ │ │ │
│ │ │ └─Annotation
│ │ │ Component.java
│ │ │
│ │ └─resources
│ └─test
然后自定义Component.java注解 在Annotation包下创建Component.java 并写如下代码:
自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}
解释:
@Target(ElementType.TYPE):此注解仅允许在类中使用
@Retention(RetentionPolicy.RUNTIME) 此注解在运行时有效
有了这个注解 我们接下来就可以对类进行标记 在之后告诉BeanFactory我们要管理这个类
接下来 要实现BeanFactory容器
BeanFactory作为一个容器,我们的需求就是 对具有@Component注解的类进行管理 读取与加载 所以我们首先要扫描整个包 处理包路径 然后获得类路径 然后扫描具有@Component注解的类 故我们首先创建一下
public class BeanFactory {
private Map<String, Object> beansMap=new HashMap<String, Object>();
public Map<String, Object> getBeansMap() {
return beansMap;
}
public BeanFactory(String basePackage){
scanBean(basePackage);
}
}
BeanFactory类 具有一个map作为属性 map的key为类的名称 value为类对象
加上一个路径构造器 传入一个base包路径
接着需要完善scanBean方法
public void scanBean(String basePackage){
//baserPackage:包路径 把包路径替换为文件路径
String path = basePackage.replace(".", "/");
URL url=this.getClass().getClassLoader().getResource(path);
//获取资源url
if (url == null) {
throw new RuntimeException("Package not found: " + basePackage);
}
File dir=new File(url.getFile());
for (File file:dir.listFiles()){
if (file.isDirectory()){
scanBean(basePackage+"."+file.getName());
} else if (file.getName().endsWith(".class")) {
String className=basePackage+"."+file.getName().replace(".class", "");
try{
//反射创建类
Class<?> clazz=Class.forName(className);
//判断是否有component注解
if (clazz.isAnnotationPresent(Component.class)){
Object instance=clazz.getDeclaredConstructor().newInstance();
//默认无参构造对象
beansMap.put(clazz.getSimpleName(), instance);
}
}catch (Exception e){
System.out.println("出现错误 反射这边");
}
}
}
}
反射部分学习与解释:
前面根据路径遍历listFiles当中的每个文件 如果文件是目录 就继续带上文件名递归扫描下一个包 知道扫描到.class类
扫描到类以后 利用反射加载类 类名就是Classname=basePackage+"."+file.getName().replace(".class", "");(全限定名)
然后判断是否有@Component注解 如果有就创建无参构造对象( Object instance=clazz.getDeclaredConstructor().newInstance();)这样就创建的一个bean
最后放进beansMap当中 BeanFactory的职责也就结束了
综上 进行测试
public class Main {
public static void main(String[] args) {
BeanFactory beanFactory=new BeanFactory("com.dms.shanshan");
System.out.println(beanFactory.getBeansMap().toString());
}
}
我们可以看到 我们将test类成功进行了管理并且能够读取到 大功告成!
本次同时学习了反射的基本原理和基本方法 和spring框架当中的容器化管理思想,也是小有成就 希望接下来能够不断完善 对spring源码有所理解
后记
仓库地址(不断更新):
全系列:杜明珅的手搓spring迷你框架系列