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

开发 前端
在GPApplicationContext中设计两个Map:factoryBeanObjectCache保存单例对象的缓存,factoryBeanInstanceCache保存GPBeanWrapper的缓存,变量命名也和原生Spring一致,这两个对象的设计其实就是注册式单例模式的经典应用。

[[440478]]

在之前的源码分析中我们已经了解到,依赖注入(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.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

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
        } 
    } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.

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

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

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(); 
            } 
 
        } 
 
    } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

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; 
    } 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

至此,DI部分就手写完成了,也就是说完成了Spring的核心部分。“小伙伴们”是不是发现其实还是很简单的?

 

责任编辑:姜华 来源: Tom弹架构
相关推荐

2021-12-27 08:27:17

SpringMVC面试

2021-12-14 07:43:52

Spring核心原理环境准备

2020-11-02 09:35:04

ReactHook

2020-12-03 08:14:45

Axios核心Promise

2011-05-31 10:00:21

Android Spring 依赖注入

2022-04-30 08:50:11

控制反转Spring依赖注入

2021-07-29 06:55:03

Spring@AutowriedbyType注入

2022-01-05 08:53:13

Spring原理分析MVC

2023-02-23 08:15:33

Spring异常处理机制

2021-02-28 20:41:18

Vue注入Angular

2016-03-21 17:08:54

Java Spring注解区别

2020-05-21 13:25:43

Spring组件架构

2009-09-08 15:22:20

Spring依赖注入

2021-08-10 18:36:02

Express原理面试

2020-11-24 07:48:32

React

2020-10-20 09:12:57

axios核心原理

2020-08-06 00:14:16

Spring IoC依赖注入开发

2023-10-07 08:35:07

依赖注入Spring

2011-03-01 13:45:41

Spring3Annotation

2022-08-27 13:49:36

ES7promiseresolve
点赞
收藏

51CTO技术栈公众号