30个类手写Spring核心原理之依赖注入功能(3)

30个类手写Spring核心原理之依赖注入功能(3)

本文节选自《Spring 5核心原理》

在之前的源码分析中我们已经了解到,依赖注入(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>();    ...}

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的核心部分。“小伙伴们”是不是发现其实还是很简单的?

本文为“Tom弹架构”原创,转载请注明出处。技术在于分享,我分享我快乐!
如果本文对您有帮助,欢迎关注和点赞;如果您有任何建议也可留言评论或私信,您的支持是我坚持创作的动力。

原创不易,坚持很酷,都看到这里了,小伙伴记得点赞、收藏、在看,一键三连加关注!如果你觉得内容太干,可以分享转发给朋友滋润滋润!

免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部