手写Spring框架
各位道友,我发现现在贼卷底层代码,看完源码发下几天后,额!!!我当时看了啥!
还是自己写个迷你的spring框架,这样印象更加深刻,上干货,代码仓库:https://gitee.com/smd_somin/SmdSpring.git
上面是我写的迷你版的spring框架,麻雀虽小,五脏俱全,主要包括下边的内容
- 容器启动
- BeanDefinition扫描
- Bean声明周期
- 单例与多例
- 依赖注入
- AOP
- aware回调
- 初始化
- BeanPostProcessor(增强器)
下面是手写框架的过程和思路,仅供大家参考!!!
相信大家总会遇到这样问题,聊聊你理解的spring?
这个基本是100个技术,99个会遇到这个问题?我谈一下我得理解,仅供参考,我认为spring可以用两行表示
//创建容器
SmdApplicationContext context = new SmdApplicationContext(AppConfig.class);
//获取对象
UserInterface userService = (UserInterface) context.getBean("userService");
在这两行代码所牵连的内容其实就是spring的本质,对与bean的管理。
如果需要容器,那么我们需要有一个容器类,下面是手写spring容器的全部代码,这个也是逻辑的核心内容,下面会分享一下思路(建议对着源码看下):
上面的代码可以整体分为两个步骤,一个创建容器,另一个是从容器中获取bean。
首先说说创建容器的过程
创建容器 -> 扫描.class文件 -> 适配文件路径 -> 判断@Component注解 -> 符合注解进行反射获取对象 -> 记录bean的信息(类型,单例)-> 创建对象 -> 实例化对象 -> 依赖注入 -> aware增强类处理 -> 处理BeanPostProcessor的 postProcessorBeforeInitialazition方法 -> 初始化 -> BeanProcessor的beanPostProcessorAfterInitailzaiton方法 ->处理切面逻辑->bean创建成功
获取bean过程
主要区分单例还是多例,单例从单例池中取,多例新创建一个bean
SmdApplicationContext
package org.smd.spring;
import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.smd.spring.annotation.Autowrite;
import org.smd.spring.annotation.Component;
import org.smd.spring.annotation.ScanComponent;
import org.smd.spring.annotation.Scope;
import org.smd.spring.aware.BeanNameAware;
import org.smd.spring.init.InitializingBean;
/**
* @author smd
* @zhName 容器
* @description: 容器
*/
public class SmdApplicationContext {
public Map<String, BeanDefinition> definitionMap = new HashMap();
public Map<String, Object> singletonBeanMap = new HashMap();
public List<BeanPostProcessor> beanPostProcessors=new ArrayList<BeanPostProcessor>();
private Class configClass;
public SmdApplicationContext(Class configClass) {
this.configClass = configClass;
//扫描文件夹下数据
if (configClass.isAnnotationPresent(ScanComponent.class)) {
ScanComponent scanComponent = (ScanComponent) configClass.getAnnotation(ScanComponent.class);
//进行文件路径转化
String path = scanComponent.vaule();
System.out.println("-->scanComponent:" + path);
path = path.replace(".", "/");
System.out.println("-->scanComponent:" + path);
//加载jar下.class文件
ClassLoader classLoader = SmdApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()) {
for (File f : file.listFiles()) {
String filePath = f.getAbsolutePath();
System.out.println("--> file path:" + filePath);
if (filePath.endsWith(".class")) {
String filesName = filePath
.substring(filePath.indexOf("org"), filePath.indexOf(".class"));
filesName = filesName.replace("\\", ".");
System.out.println("-->file name" + filesName);
try {
Class<?> clazz = classLoader.loadClass(filesName);
if (clazz.isAnnotationPresent(Component.class)) {
if(BeanPostProcessor.class.isAssignableFrom(clazz)){
BeanPostProcessor beanPostProcessor=(BeanPostProcessor) clazz.newInstance();
beanPostProcessors.add(beanPostProcessor);
}
Component component = clazz.getAnnotation(Component.class);
//获取bean name
String name = component.vaule();
if (name.equals("")) {
name = Introspector.decapitalize(clazz.getSimpleName());
}
//记录bean definition
BeanDefinition definition = new BeanDefinition();
definition.setType(clazz);
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scope = (Scope) clazz.getAnnotation(Scope.class);
definition.setScope(scope.value());
} else {
definition.setScope("singleton");
}
//放入bean definition map中
definitionMap.put(name, definition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
}
}
//初始化bean
for (String name : definitionMap.keySet()) {
BeanDefinition definition = definitionMap.get(name);
Object bean = this.createBean(name, definition);
singletonBeanMap.put(name, bean);
}
}
private Object createBean(String name, BeanDefinition definition) {
Class clazz = definition.getType();
try {
//实例化
Object bean = clazz.getConstructor().newInstance();
//依赖注入
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowrite.class)) {
field.setAccessible(true);
field.set(bean, getBean(field.getName()));
}
}
// aware加强类回调
if(bean instanceof BeanNameAware){
((BeanNameAware)bean).setBeanName(name);
}
// 初始化前调用bean post processor
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
bean= beanPostProcessor.postProcessorBeforeInitialization(name,bean);
}
// 初始化
if(bean instanceof InitializingBean){
((InitializingBean)bean).afterPropertiesSet();
}
// 初始化后调用bean post processor
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
bean= beanPostProcessor.postProcessorAftertInitialization(name,bean);
}
return bean;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public Object getBean(String name) {
//获取definition信息
BeanDefinition definition = definitionMap.get(name);
if (definition == null) {
System.out.println("-->error:" + name);
throw new NullPointerException();
} else {
//进行单例和多例区分
if (definition.getScope().equals("singleton")) {
Object bean = singletonBeanMap.get(name);
if (bean == null) {
return this.createBean(name, definition);
} else {
return bean;
}
} else {
return this.createBean(name, definition);
}
}
}
}
各位道友前路漫漫~ 努力向远方前进吧!!!文章来源:https://www.toymoban.com/news/detail-457019.html
《真常之道,悟者自得,得悟道者,常清静矣。》文章来源地址https://www.toymoban.com/news/detail-457019.html
到了这里,关于手写Spring框架的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!