手记

spring源码分析(二)bean的生命周期之bean的扩展

目标:我们学习spring的源码的主要目的: 对bean的扩展

package com.springbeanDemo.config;

import com.springbeanDemo.pojo.Product;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;

/**
 * 注释
 *
 * @author sunhao
 * @Date 2021-08-09-20:49
 */
@Component
public class springBeanFactory implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        final GenericBeanDefinition bean = (GenericBeanDefinition) configurableListableBeanFactory.getBeanDefinition("bean1");
        bean.setBeanClass(Bean2.class);
    }
}

1.我们需要实现BeanFactoryPostProcessor接口的postProcessBeanFactory方法 他会有一个 ConfigurableListableBeanFactory类型的参数configurableListableBeanFactory 就是我们常说的spring工厂。

2.这个工厂中存在一个map
💣注意这里说的不是单例池的map
上一篇文章讲到过 在Bean初始化的过程中会把属性都注入到BeanFactoryDefinition对象,然后再把BeanFactoryDefinition对象放入到一个map中,从这里就得到了证实。beanDefinitionMap

public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
        BeanDefinition bd = (BeanDefinition)this.beanDefinitionMap.get(beanName);
        if (bd == null) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("No bean named '" + beanName + "' found in " + this);
            }

            throw new NoSuchBeanDefinitionException(beanName);
        } else {
            return bd;
        }
    }

3.对bean的扩展

final GenericBeanDefinition bean = (GenericBeanDefinition) configurableListableBeanFactory.getBeanDefinition("bean1");
bean.setBeanClass(Bean2.class);

在这里通过名字configurableListableBeanFactory.getBeanDefinition("bean1");去找到这个BeanFactoryDefinition对象然后 这里是重点
bean.setBeanClass(Bean2.class);
他把另外一个类 Bean2.class 放到里面 这时候 Bean1.class就不存在在我们的工厂里面了

package com;

import com.springbeanDemo.config.Config;
import com.springbeanDemo.pojo.Product;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * 注释
 * 验证是不是置换了value  用原来的key还能取到
 * @author sunhao
 * @Date 2021-08-09-20:46
 */
public class Main {
    public static void main(String[] args) {
        final AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
        System.out.println(ac.getBean(Bean2.class));
        System.out.println(ac.getBean("bean1"));
        System.out.println(ac.getBean(Bean2.class) == ac.getBean("bean1"));
    }
}

请记住这里的ac.getBean(“bean1”)会产生疑惑 他取出来的是Bean2.class
我们通过ac.getBean(Bean2.class) 和 ac.getBean(“bean1”) 获取到的对象是同一个 都是Bean2.class 这里验证了 bean.setBeanClass(Bean2.class); 只是把beanClass 这个属性换了。他到了创建bean的那一步就会根据Bean2.class反射去寻找类

我们如果想通过ac.getBean("bean2") 获取到这个Bean2.class的话 需要加上
bean.setBeanClassName(“bean2”);

@Component
public class springBeanFactory implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        final GenericBeanDefinition bean = (GenericBeanDefinition) configurableListableBeanFactory.getBeanDefinition("bean1");
        bean.setBeanClass(Bean2.class);
        bean.setBeanClassName("bean2");
    }
}

@Component这个类上加上扫描注解才会生效

总结:

这里还没有到创建对象的那一步,上一篇文章中说过 对BeanFactoryDefinition扩展完成后 他会根据BeanFactoryDefinition中的属性决定是否去立即创建bean
这里可以理解为 他现在更改的是创建bean之前的那个模板
更改后他就会根据更改之后的模板去创建这个bean到单例池map中

1人推荐
随时随地看视频
慕课网APP