02_手写模拟Spring底层原理
参考spring的使用方式:
// 创建一个Spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.test();
设计模拟spring使用方式:
新增spring包:
新增YyjApplicationContext模拟spring启动类,新增构造方法和getBean方法:
public class YyjApplicationContext {
private Class configClass;
public YyjApplicationContext(Class configClass) {
this.configClass = configClass;
}
public Object getBean(String beanName) {
}
}
新增扫描方法扫描bean,并放入beanDefinitionMap中用于后期创建bean,在构造方法中调用scan()方法:
private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
private void scan(Class configClass) {
// 从ComponentScan中拿到扫描路径
if (configClass.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
String path = componentScanAnnotation.value();
path = path.replace(".", "/"); // com/yyj/service
// 拿到自己的类加载器,用来加载扫描路径下的bean
ClassLoader classLoader = YyjApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
if (resource == null) {
return;
}
File file = new File(resource.getFile());
if (file.isDirectory()) {
for (File f : Objects.requireNonNull(file.listFiles())) {
String absolutePath = f.getAbsolutePath();
// 所有的.class文件的路径如:com\yyj\service\OrderService
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");
try {
// 加载类
Class<?> clazz = classLoader.loadClass(absolutePath);
if (clazz.isAnnotationPresent(Component.class)) {
Component componentAnnotation = clazz.getAnnotation(Component.class);
String beanName = componentAnnotation.value();
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
String value = scopeAnnotation.value();
beanDefinition.setScope(value);
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
createBean的核心逻辑:
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getType();
Object instance = null;
try {
// 创建实例
instance = clazz.getConstructor().newInstance();
// 依赖注入逻辑
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
field.set(instance, getBean(field.getName()));
}
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
构造方法中将扫描到单例bean的BeanDefinition进行创建到并放到单例池中:
private final Map<String, Object> singletonObjects = new HashMap<>();
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
}
从容器中获取bean的核心逻辑getBean方法:
public Object getBean(String beanName) {
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
// 单例bean
if (beanDefinition.getScope().equals("singleton")) {
Object singletonBean = singletonObjects.get(beanName);
// 若还未创建时就获取,就先创建
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
return singletonBean;
} else {
// 原型
return createBean(beanName, beanDefinition);
}
}
bean的扩展点BeanPostProcessor的核心逻辑:#
增加接口:
package com.spring;
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
在扫描过程中将扫描到的BeanPostProcessor添加到beanPostProcessorList中:
private final List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
// 判断一个类是否实现了BeanPostProcessor接口
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();
beanPostProcessorList.add(instance);
}
在创建bean的过程中执行扩展点beanPostProcessorList中的逻辑:
// bean的前置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
// bean的后置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
扩展点InitializingBean的实现:#
新增接口InitializingBean:
package com.spring;
public interface InitializingBean {
void afterPropertiesSet();
}
扫描到的bean若实现了该接口则会在创建过程中执行该实现方法:
// bean的前置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
// 初始化
if (instance instanceof InitializingBean) {
((InitializingBean) instance).afterPropertiesSet();
}
// bean的后置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
Aware 回调方法的实现以BeanNameAware为例:#
增加接口BeanNameAware:
package com.spring;
public interface BeanNameAware {
void setBeanName(String name);
}
扫描到的bean若实现了该接口则在创建bean的过程中会执行该接口实现方法的逻辑并将beaname作为参数:
// Aware 回调方法
if (instance instanceof BeanNameAware) {
((BeanNameAware) instance).setBeanName(beanName);
}
// bean的前置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
// 初始化
if (instance instanceof InitializingBean) {
((InitializingBean) instance).afterPropertiesSet();
}
// bean的后置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)