飙血推荐
  • HTML教程
  • MySQL教程
  • JavaScript基础教程
  • php入门教程
  • JavaScript正则表达式运用
  • Excel函数教程
  • UEditor使用文档
  • AngularJS教程
  • ThinkPHP5.0教程

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

时间:2021-12-12  作者:gupaoedu-tom  

本文节选自《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 = 域名(beanName);

        try{

            //生成通知事件
            GPBeanPostProcessor beanPostProcessor = new GPBeanPostProcessor();

            Object instance = instantiateBean(beanDefinition);
            if(null == instance){ return  null;}

            //在实例初始化以前调用一次
            域名ProcessBeforeInitialization(instance,beanName);

            GPBeanWrapper beanWrapper = new GPBeanWrapper(instance);

            域名(beanName,beanWrapper);

            //在实例初始化以后调用一次
            域名ProcessAfterInitialization(instance,beanName);

            populateBean(beanName,instance);

            //通过这样调用,相当于给我们自己留有了可操作的空间
            return 域名(beanName).getWrappedInstance();
        }catch (Exception e){
//            域名tStackTrace();
            return null;
        }
    }

2 instantiateBean()方法反射创建实例


    //传一个BeanDefinition,就返回一个实例Bean
    private Object instantiateBean(GPBeanDefinition beanDefinition){
        Object instance = null;
        String className = 域名eanClassName();
        try{

            //因为根据Class才能确定一个类是否有实例
            if(域名ainsKey(className)){
                instance = 域名(className);
            }else{
                Class<?> clazz = 域名ame(className);
                instance = 域名nstance();

                域名(域名actoryBeanName(),instance);
            }

            return instance;
        }catch (Exception e){
            域名tStackTrace();
        }

        return null;
    }
		

3 populateBean()方法完成依赖注入


    private void populateBean(String beanName,Object instance){

        Class clazz = 域名lass();

        if(!(域名notationPresent(域名s) ||
                域名notationPresent(域名s))){
            return;
        }

        Field [] fields = 域名eclaredFields();

        for (Field field : fields) {
            if (!域名notationPresent(域名s)){ continue; }

            GPAutowired autowired = 域名nnotation(域名s);

            String autowiredBeanName = 域名e().trim();

            if("".equals(autowiredBeanName)){
                autowiredBeanName = 域名ype().getName();
            }

            域名ccessible(true);

            try {

                域名(instance,域名(autowiredBeanName). getWrappedInstance());

            } catch (IllegalAccessException e) {
//                域名tStackTrace();
            }

        }

    }
		

4 GPBeanPostProcessor后置处理器

原生Spring中的BeanPostProcessor是为对象初始化事件设置的一种回调机制。这个Mini版本中只做说明,不做具体实现,感兴趣的“小伙伴”可以继续深入研究Spring源码。


package 域名域名域名ig;

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

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

标签:编程
湘ICP备14001474号-3  投诉建议:234161800@qq.com   部分内容来源于网络,如有侵权,请联系删除。