在之前的源码分析中我们已经了解到,依赖注入(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
factoryBeanObjectCache = new HashMap(); -
- //用来存储所有的被代理过的对象
- private Map
factoryBeanInstanceCache = new ConcurrentHashMap(); -
- ...
-
- }
1 从getBean()方法开始
下面我们从完善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;
- }
- }
2 instantiateBean()方法反射创建实例
- //传一个BeanDefinition,就返回一个实例Bean
- private Object instantiateBean(GPBeanDefinition beanDefinition){
- Object instance = null;
- String className = beanDefinition.getBeanClassName();
- try{
-
- //因为根据Class才能确定一个类是否有实例
- if(this.factoryBeanObjectCache.containsKey(className)){
- instance = this.factoryBeanObjectCache.get(className);
- }else{
- Class> clazz = Class.forName(className);
- instance = clazz.newInstance();
-
- this.factoryBeanObjectCache.put(beanDefinition.getFactoryBeanName(),instance);
- }
-
- return instance;
- }catch (Exception e){
- e.printStackTrace();
- }
-
- return null;
- }
3 populateBean()方法完成依赖注入
- private void populateBean(String beanName,Object instance){
-
- Class clazz = instance.getClass();
-
- if(!(clazz.isAnnotationPresent(GPController.class) ||
- clazz.isAnnotationPresent(GPService.class))){
- return;
- }
-
- Field [] fields = clazz.getDeclaredFields();
-
- for (Field field : fields) {
- if (!field.isAnnotationPresent(GPAutowired.class)){ continue; }
-
- GPAutowired autowired = field.getAnnotation(GPAutowired.class);
-
- String autowiredBeanName = autowired.value().trim();
-
- if("".equals(autowiredBeanName)){
- autowiredBeanName = field.getType().getName();
- }
-
- field.setAccessible(true);
-
- try {
-
- field.set(instance,this.factoryBeanInstanceCache.get(autowiredBeanName). getWrappedInstance());
-
- } catch (IllegalAccessException e) {
- // e.printStackTrace();
- }
-
- }
-
- }
4 GPBeanPostProcessor后置处理器
原生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的核心部分。“小伙伴们”是不是发现其实还是很简单的?