在之前的个类源码分析中我们已经了解到,依赖注入(DI)的手写入口是getBean()方法,前面的核心IoC手写部分基本流程已通。先在GPApplicationContext中定义好IoC容器,原理然后将GPBeanWrapper对象保存到Map中。赖注在GPApplicationContext中设计两个Map:factoryBeanObjectCache保存单例对象的入功缓存,factoryBeanInstanceCache保存GPBeanWrapper的个类缓存,变量命名也和原生Spring一致,手写这两个对象的核心设计其实就是云服务器注册式单例模式的经典应用。
public class GPApplicationContext extends GPDefaultListableBeanFactory implements GPBeanFactory { private String [] configLocations; private GPBeanDefinitionReader reader; //用来保证注册式单例的原理容器 private Map<String,Object> factoryBeanObjectCache = new HashMap<String, Object>(); //用来存储所有的被代理过的对象 private Map<String,GPBeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<String, GPBeanWrapper>(); ... }下面我们从完善getBean()方法开始:
@Override public Object getBean(String beanName) { GPBeanDefinition beanDefinition = super.beanDefinitionMap.get(beanName); try{ //生成通知事件 GPBeanPostProcessor beanPostProcessor = new GPBeanPostProcessor(); Object instance = instantiateBean(beanDefinition); if(null == instance){ return null;} //在实例初始化以前调用一次 beanPostProcessor.postProcessBeforeInitialization(instance,beanName); GPBeanWrapper beanWrapper = new GPBeanWrapper(instance); this.factoryBeanInstanceCache.put(beanName,beanWrapper); //在实例初始化以后调用一次 beanPostProcessor.postProcessAfterInitialization(instance,beanName); populateBean(beanName,instance); //通过这样调用,相当于给我们自己留有了可操作的赖注空间 return this.factoryBeanInstanceCache.get(beanName).getWrappedInstance(); }catch (Exception e){ // e.printStackTrace(); return null; } }原生Spring中的BeanPostProcessor是为对象初始化事件设置的一种回调机制。这个Mini版本中只做说明,个类不做具体实现,服务器托管手写感兴趣的核心“小伙伴”可以继续深入研究Spring源码。
package com.tom.spring.formework.beans.config; public class GPBeanPostProcessor { //为在Bean的初始化之前提供回调入口 public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception { return bean; } //为在Bean的初始化之后提供回调入口 public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception { return bean; } }至此,DI部分就手写完成了,也就是说完成了Spring的核心部分。“小伙伴们”是不是发现其实还是很简单的?