-
spring-ioc的极简实现
简介
spring ioc的极简实现,可以完成自动属性注入,使用二级缓存解决循环依赖(就是把半成品对象放个map里先保存着),基于注解,可以指定配置文件,总计不到100行代码,可以简单对spring依赖注入有个大致的了解,项目下载链接在文末
大概步骤
最基本的注解
Autowired注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
Component注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}
ComponentScan注解(这个注解其实也可以不要,比如默认就扫描main方法目录)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
String value();
}
Application类
用来解析配置文件,创建bean
public class Application {
Map<Class<?>,Object> singletonInstance =new HashMap<>();
Map<Class<?>,Object> earlySingletonInstance=new HashMap<>();
Set<Class<?>> classSet=new HashSet<>();
public Application(Class<?> configClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//获得扫描路径
String path = configClass.getDeclaredAnnotation(ComponentScan.class).value();
ClassLoader classLoader = Application.class.getClassLoader();
//获得扫描路径下所有文件
for (File file : new File(classLoader.getResource(path.replace(".","/")).getFile()).listFiles()) {
//这里没有递归处理,只扫描第一层的class文件
if(!file.getName().endsWith(".class"))continue;
String fullName=(path+"."+file.getName()).replace(".class","");
Class<?> aClass = classLoader.loadClass(fullName);
//保存所有被Component注解的类
if(aClass.isAnnotationPresent(Component.class))classSet.add(aClass);
}
//生成半成品对象放到二级缓存
for (Class<?> aClass : classSet) earlySingletonInstance.put(aClass,aClass.newInstance());
//Autowired属性注入
for (Class<?> aClass : classSet){
Object instance = earlySingletonInstance.get(aClass);
for (Field field : aClass.getDeclaredFields()) {
if(field.isAnnotationPresent(Autowired.class)){
field.setAccessible(true);
field.set(instance,earlySingletonInstance.get(field.getType()));
}
}
//放到单例池
singletonInstance.put(aClass, instance);
}
}
//按类型获取,生成的都是单例bean
public <T> T getBean(Class<T> clazz){
return clazz.cast(singletonInstance.get(clazz));
}
}
测试
Calculate.java,Service.java这两个文件位于io.spring.test
目录下
@Component
public class Calculate {
@Autowired
private Service service;
public int add(int x,int y){
return service.add(x, y);
}
}
@Component
public class Service {
@Autowired
Calculate calculate;//测试循环依赖
public int add(int x, int y) {
return x+y;
}
}
@ComponentScan("io.spring.test")//扫描路径
public class App {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Application appContext = new Application(App.class);//初始化
Calculate cal = appContext.getBean(Calculate.class);//获得bean对象
System.out.println(cal.add(3,5));
}
}
测试程序输出8
,说明依赖注入的目的达到了
项目下载
https://github.com/fuchengshun/simple-spring-ioc
原文:https://www.cnblogs.com/fuchengshun/p/14732279.html
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
JavaScript判断两个数组相等的四类方法
js如何操作video标签
React实战--利用甘特图和看板,强化Paas平
【记录】正则替换的偏方
前端下载 Blob 类型整理
抽象语法树AST必知必会
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程