纯手写实现Spring源码框架(五)依赖注入

前言
上一篇我们讲解了包实例化的前期准备工作,创建缓存,构建体系,移入准备,移除准备。这篇来处理后置处理器的注入和实例的生成


构建后置处理器体系
在这里插入图片描述
换个思路讲解,我们开始进入refresh()刷新容器中,第一步创建工厂,第二步注册后置处理器


第一部分代码:关于如何获取到后置处理器的派生类,如何拿到实例放入缓存

  @Override
        public void refresh() {
            synchronized (startupShutdownMonitor) {
                // 创建工厂对象
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
                //注册后置处理器
                registerBeanPostProcessors(beanFactory);
                // 实例化所有单例作用域(Singleton)Bean定义的实例
                finishBeanFactoryInitialization(beanFactory);
            }
        }
        private void   registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//委托类,委托类负责注入
            PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
        }

委托类的实现


/**
 * 后置处理的注册委托类
 */
public class PostProcessorRegistrationDelegate {
    /**
     * 构建后置处理器
     * @param beanFactory
     * @param abstractApplicationContext
     */
    public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext abstractApplicationContext){
        // 获取所有关于BeanPostProcessor类型的beanName集合
        //传入主类,传入是否包含单列,传入是否费及时加载
        //下面有getBeanNamesForType方法详解
        String[] postProcessorNames = beanFactory
                .getBeanNamesForType(BeanPostProcessor.class, true, false);

        Set<BeanPostProcessor> postProcessors = new HashSet<>();
        //再遍历集合从工厂中拿到实例的集合
        for (String postProcessorName : postProcessorNames) {
            // 获取后期处理名称对应实例
            BeanPostProcessor postProcessor = beanFactory.getBean(postProcessorName, BeanPostProcessor.class);
            // 把生成后置处理器的实例放入集合中
            postProcessors.add(postProcessor);
        }
        // 注册所有的BeanPostProcessor实例
        registerBeanPostProcessors(beanFactory, postProcessors);
    }
    /**
     * 注册所有的BeanPostProcessor实例放进工厂
     * @param beanFactory
     */
    private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, Set<BeanPostProcessor> postProcessors){
        for (BeanPostProcessor postProcessor : postProcessors) {
        //放入工厂
            beanFactory.addBeanPostProcessor(postProcessor);
        }
    }
}

getBeanNamesForType获取关于是否是当前类的派生类,如果是则存入集合

  /**
     * 获取所有派生类的BeanName
     * @param type
     * @param includeNonSingletons
     * @param allowEagerInit
     * @return
     */
    @Override
    public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
        Set<String> beanNameSet = new LinkedHashSet<>();
        beanDefinitionMap.forEach((beanName,beanDefinition)->{
            Class<?> aClass = beanDefinition.getbeanClass();
            //判断是不是派生类
            if (type.isAssignableFrom(aClass)) {
                //是则拿到集合
                beanNameSet.add(beanName);
            }
        });
        return beanNameSet.toArray(new String[0]);
    }

addBeanPostProcessor添加进缓存集合,beanPostProcessors是个线程安全集合

   /** BeanPostProcessors to apply in createBean. */
    private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        // Remove from old position,
        //先移除掉,保证集合里是最新的后置处理器
        this.beanPostProcessors.remove(beanPostProcessor);
        if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
            this.hasInstantiationAwareBeanPostProcessors = true;
        }

        this.beanPostProcessors.add(beanPostProcessor);
    }

第二部分,原始后置处理器注入

注入原生后置处理器

//internalAutowiredAnnotationProcessor后置处理器地址
    public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
            "org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
 /**
     * 注册默认的注解解析后置处理器
     * @param registry
     * @param source
     */
    public static void registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, Object source) {
        if 
        //检查是否包含注册体系
        (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            //将对象注入工厂
            registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME);
        }
    }

    private static void registerPostProcessor(
            BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
        registry.registerBeanDefinition(beanName, definition);
    }
    
 @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
    //将后置处理器放入集合当中
        synchronized (monitor){
            if (!beanDefinitionMap.containsKey(beanName)){
                beanDefinitionMap.put(beanName,beanDefinition);
                this.beanDefinitionNames.add(beanName);
            }
        }
    }

第三部分,依赖注入实例化
思路,反射寻找到所有字段,遍历字段集合,寻找标注了注解的字段,
找到后根据类型和名字进行匹配,匹配到后,找到getBean获取类型实例。
核心代码

  /**
     * 开始处理对象依赖注入(只提供字段注入)
     * @param bean
     * @param beanName
     * 装配规则:
     * 1、首先按照类型装配,如果只有一个符合bean就直接注入
     * 2、如果发现有多个同类型的实例,就按照名称装配
     */
    @Override
    public void postProcessProperties(Object bean, String beanName) {
        //找到依赖注入的字段属性集合
        //只提供字段的注入
        //找到需要装配的字段
        List<Field> injectFields = findAutowiringMetadata(bean, beanName);
        if (injectFields.size() == 0) {
            return;
        }
        /**
         * 装配规则
         * 1.首先按类型装配,如果只有一个符合的类型直接装配
         * 2.如果有多个相同的类型按名称装配
         */
        for (Field injectField : injectFields) {
            Object injectInstance = null;
            // 获取注入的字段类型
            Class<?> type = injectField.getType();
            String[] names = beanFactory.getBeanNamesForType(type, true, false);
            if (names!= null && names.length == 1) {
                // 如果这个类型只有一个
                injectInstance = beanFactory.getBean(names[0]);
            } else if (names != null && names.length > 1){
                // 如果发现类型有多个,只能按照名称装配
                for (String name : names) {
                    if (name.equals(injectField.getName())) {
                        injectInstance = beanFactory.getBean(name);
                        break;
                    }
                }
            }
            try {
                // 使用反射设置当前bean对应依赖对象的值
                injectField.setAccessible(true);
                injectField.set(bean, injectInstance);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

在上面的核心代码中beanFactory.getBean(names[0]);其实就是dogetBean里面的从三级缓存里拿对象,包括我们对外暴露的其实也是从三级缓存里拿,如果有直接返回Bean没有则去构建

findAutowiringMetadata 找到需要装配的字段

   private final Map<String, List<Field>> injectionFieldCache = new ConcurrentHashMap<>(256);
 /**
     * 寻找包含autowired的字段属性
     * @param bean
     * @param beanName
     * @return
     */
    private List<Field> findAutowiringMetadata(Object bean, String beanName) {
        List<Field> fields = this.injectionFieldCache.get(beanName);
        //如果需要获取的字段为空则进入进行寻找需要生成的字段,如果存在则直接返回
        if (fields==null){
            fields=new ArrayList<>();
        for (Class<? extends Annotation> autowiredAnnotationType : autowiredAnnotationTypes) {
            // 获取当前bean对应
            Field[] declaredFields = bean.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                //判断是否包含autowired这个注解
                if (declaredField.isAnnotationPresent(autowiredAnnotationType)) {
                    fields.add(declaredField);
                }
            }
            //把需要生成的字段属性放入map集合,
            this.injectionFieldCache.put(beanName, fields);
        }
        }
        return fields;
    }

doGetBean核心代码

  protected <T> T doGetBean(final String beanName,final Class<T> requiredType,
                              final Object[] args, boolean typeCheckOnly) {
        Object bean = null;
        /**
         *     获取缓存中存储的与当前beanName对应实例
         *     private Object getObjectForBeanInstance(Object sharedInstance, String beanName, Object o) {
         *         // 扩展基于FactoryBean实例方式
         *         return sharedInstance;
         *     }
         */
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            //源代码这里是工厂实例化校验我们直接返回Bean就行
            bean = getObjectForBeanInstance(sharedInstance, beanName, null);
        }
        else {
            if (!typeCheckOnly) {
                //标记当前BeanName正在被构建
                markBeanAsCreated(beanName);
            }

            try {
                //通过BeanName拿到对象包装为RootBeanDefinition,RootBeanDefinition为需要注入的单例Bean类型
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // 根据bean定义作用域类型来创建实例
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            //创建Bean
                            return createBean(beanName, mbd, args);
                        } catch (Exception ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            //如果出现了异常需要把校验缓存移除掉
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    //源代码这里是工厂实例化校验我们直接返回Bean就行
                    bean = getObjectForBeanInstance(sharedInstance, beanName, mbd);
                } else if (mbd.isPrototype()) {
                          //是否多列,这里我们不写,只写主流单列
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (requiredType != null) {
                // 判断获取的类型是否与需求类型一致
                if (!requiredType.isAssignableFrom(bean.getClass())) {
                    throw new RuntimeException("创建的类型与期望类型不一致");
                }
            }
        }
        return (T) bean;
    }

单列Bean的实现

 ///注入单列Bean
    protected Object initializeBean(String beanName, Object exposedObject, RootBeanDefinition mbd){
        if (exposedObject instanceof Aware) {
            // 判断是否为某个具体扩展接口
            if (exposedObject instanceof BeanFactoryAware) {
                // 回调对应实现类中setBeanFactory方法
                ((BeanFactoryAware) exposedObject).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
        return exposedObject;
 };

setBeanFactory方法是给将现在已经有了缓存抽象工厂对象重新赋值给属性。

测试
在这里插入图片描述
成功输出了依赖对象Dao中的hello方法

感悟
对于构建感悟
好像没有什么重点需要提及到了,整个代码花了我一周半的时间,大部分时间都花在阅读上了,我如果有读者连续读就应该发现了我每一篇讲述的方法都不一样,因为越到很面很多类的方法交叉,实在不好用文章这样线性的方法讲述出来,只好写出关键代码,重要的流程,一些warpper,rootbeandinition这样的特定下的特定封装类我就没编写了,这样的类也有自己接口体系,实在复杂,不过主线清楚了其他就是旁门左道。

对于Spring感悟
其实Spring的核心其实也是一些基础流程+设计模式,工厂设计模式,代理设计模式,模板设计模式,还有一些设计巧妙的地方。
基础流程,就我们在只有路径的情况下,根据现有条件如何去解析文件,去寻找我们符合条件的文件,比如类路径解析路径下的所有文件,有了文件解析类的特征元数据,再按一定规则去设置元数据的值,再根据元数据的值去包装这个文件,包装成符合需求特征的文件进行处理,几乎所有都是这样的思想进行下去的。

对于整个框架单一职责是体会最深刻的,很多明明可以自己完成的但是也要明确给别人,哪怕没有继承关系,也要通过继承相同接口,交由别人实现。

后续会再读几次吧。

百度云:https://pan.baidu.com/s/1ZnCLzItaXjIbTcnLEg0iaw
密码:gfe8

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值