Spring框架很庞大和复杂,为了更好的理解其实现,尝试去模仿其功能手写一个简易版本,暂时只包括简略的几个功能,为了看情况更新。
1. 包含功能
- @ComponentScan包体扫描
- @Autowire依赖注入
- @Scope单例实现
- BeanPostProcessor后置处理器
- InitializingBean初始化bean接口
- BeanNameAware名字资源设置
- BeanDefinition定义
- SingletonObjects单例池
- BeanDefinitionMap池
- 基于注解配置的ApplicationContext
2.逻辑
public class main {
public static void main(String[] args) {
EndwasApplicationContext context = new EndwasApplicationContext(AppConfig.class);
EndwasService endwasService = (EndwasService) context.getBean("endwasService");
endwasService.execute();
}
}
和普通Spring容器使用一样,需要创建容器并传入配置类,然后去获取bean。
public EndwasApplicationContext(Class<?> configClass) {
if (configClass == null) {
throw new EndwasException("configClass can not null!");
}
this.configClass = configClass;
init();
}
而容器的初始化分为三步
- 获取配置类@ComponetScan扫描的包体 例如com.endwas.context,如果没设置就扫描该类所在包体。
- 扫描当前文件夹和子文件夹,进行BeanDefinition创建和保存元数据。
- 对singleton的bean创建保存进单例池singletonObjects。
private void init() {
// 初始化 1、扫描 -> beanDefinitionMap 2、创建到singletonObjects
String packageName = getPackagePath();
// 扫描
scan(packageName);
// 创建bean
createBean();
}
获取bean,如果是单例的bean只需要在单例池直接拿就好了,而非单例则获取的时候创建。两者在创建的时候都是调用createBean方法。
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class<?> clazz = beanDefinition.getClazz();
Object bean = null;
try {
// 1.实例bean
bean = clazz.getDeclaredConstructor().newInstance();
// 2.依赖注入
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class)) {
Object value = getBean(field.getName());
field.setAccessible(true);
field.set(bean, value);
}
}
// 3.Aware回调
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
// 如果是BeanPostProcessor则不调用before/after
if (bean instanceof BeanPostProcessor) {
initBean(clazz, bean);
return bean;
}
// 4.beanPostProcessor::postProcessBeforeInitialization
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
bean = beanPostProcessor.postProcessBeforeInitialization(bean, beanName);
}
initBean(clazz, bean);
// 6.beanPostProcessor::postProcessAfterInitialization aop动态代理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
bean = beanPostProcessor.postProcessAfterInitialization(bean, beanName);
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
return bean;
}
该方法包括
- 调用默认的构造方法创建。
- 依赖注入
- 如果实现了aware回调
- 调用beanPostProcessor::postProcessBeforeInitialization
- 初始化bean(执行postConstruct、InitializingBean)
- 调用beanPostProcessor::postProcessAfterInitialization
这里要说明一点postConstruct是在后置处理器初始化前执行的,这里放到和afterPropertiesSet一起执行
3.源码
上传到了github上,还在不定时完善。 https://github.com/Endwas/EndwasApplicationContext
4.next
后续打算
- 支持resource、inject等注解。
- PostConstruct修改实现位置。
- 支持ComponentScan多路径。
评论