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

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

作者: Tom弹架构 | 来源:发表于2021-12-12 18:18 被阅读0次

    本文节选自《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弹架构 』回复“Spring”可获取完整源码。

    本文为“Tom弹架构”原创,转载请注明出处。技术在于分享,我分享我快乐!如果您有任何建议也可留言评论或私信,您的支持是我坚持创作的动力。关注『 Tom弹架构 』可获取更多技术干货!

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

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/niorfrtx.html