当前位置: 首页 > 后端技术 > Java

30课手写Spring核心原理依赖注入函数(三)

时间:2023-04-01 13:45:24 Java

本文节选自《Spring 5核心原理》在前面的源码分析中,我们了解到依赖注入(DI)的入口是getBean()方法,而之前的IoC手写部分的基本流程已经通过了。先在GPApplicationContext中定义IoC容器,然后将GPBeanWrapper对象保存到Map中。在GPApplicationContext中设计两个Map:factoryBeanObjectCache保存单例对象的缓存,factoryBeanInstanceCache保存GPBeanWrapper的缓存。变量名也和原生Spring保持一致。这两个对象的设计其实就是注册单例模式的经典应用。公共类GPApplicationContext扩展GPDefaultListableBeanFactory实现GPBeanFactory{privateString[]configLocations;私人GPBeanDefinitionReader读者;//用于保证注册单例的容器privateMapfactoryBeanObjectCache=newHashMap();//用于存储所有代理对象privateMapfactoryBeanInstanceCache=newConcurrentHashMap();...}1从getBean()方法开始让我们从改进getBean()方法开始:@OverridepublicObjectgetBean(StringbeanName){GPBeanDefinitionbeanDefinition=super.beanDefinitionMap.get(beanName);try{//生成通知事件GPBeanPostProcessorbeanPostProcessor=newGPBeanPostProcessor();对象实例=instantiateBean(beanDefinition);if(null==instance){returnnull;}//实例初始化前调用一次beanPostProcessor.postProcessBeforeInitialization(instance,beanName);GPBeanWrapperbeanWrapper=newGPBeanWrapper(实例);this.factoryBeanInstanceCache.put(beanName,beanWrapper);//调用beanPostProcessor.postProcessAfterInitialization(instance,beanName);populateBean(beanName,实例);//这样调用,相当于给自己留了一个可操作的空间returnthis.factoryBeanInstanceCache.get(beanName).getWrappedInstance();}catch(Exceptione){//e.printStackTrace();返回空值;}}2instantiateBean()方法反射创建一个实例//传递一个BeanDefinition,返回一个Bean实例privateObjectinstantiateBean(GPBeanDefinitionbeanDefinition){Objectinstance=null;字符串类名=beanDefinition.getBeanClassName();try{//因为是根据Class来判断一个类是否有Instanceif(this.factoryBeanObjectCache.containsKey(className)){instance=this.factoryBeanObjectCache.get(className);}else{类clazz=Class.forName(className);instance=clazz.newInstance();this.factoryBeanObjectCache.put(beanDefinition.getFactoryBeanName(),实例);}返回实例;}catch(Exceptione){e.printStackTrace();}返回空值;}3populateBean()方法完成依赖注册privatevoidpopulateBean(StringbeanName,Objectinstance){Classclazz=instance.getClass();if(!(clazz.isAnnotationPresent(GPController.class)||clazz.isAnnotationPresent(GPService.class))){返回;}字段[]字段=clazz.getDeclaredFields();for(Fieldfield:fields){if(!field.isAnnotationPresent(GPAutowired.class)){继续;}GPAutowiredautowired=field.getAnnotation(GPAutowired.class);StringautowiredBeanName=autowired.value().trim();if("".equals(autowiredBeanName)){autowiredBeanName=field.getType().getName();}field.setAccessible(true);尝试{field.set(实例,this.factoryBeanInstanceCache.get(autowiredBeanName).getWrappedInstance());}catch(IllegalAccessExceptione){//e.printStackTrace();}}}4GPBeanPostProcessor原生Spring中的后处理器BeanPostProcessor是为对象初始化事件设置的回调机制。本Mini版仅做说明,不做具体实现。小伙伴们可以继续深入研究Spring源码。throwsException{returnbean;}//为Bean提供publicObject初始化后的回调入口postProcessAfterInitialization(Objectbean,StringbeanName)throwsException{returnbean;}}至此DI部分已经手写完毕,即话说,Spring的核心部分已经完成了,“小伙伴们”有没有发现其实很简单呢?