这一行代码到底做了什么~终篇

每天叫醒你的不是闹钟,而是梦想

续言

    前面我们已经提到Spring的BeanFactory工厂了,回顾请点击 -> 这一行代码到底做了什么?,那么我们如何通过这个BeanFactory来干涉Spring Bean的构建呢?

● BeanFactoryPostProcessor的使用

    Spring为了让我们方便干涉Bean工厂,提供一个BeanFactoryPostProcessor接口。

@Component
public class BeanFactoryPostProcessorImpl implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        //  获取memberService得BeanDefinition对象。
        GenericBeanDefinition memberDefinition = (GenericBeanDefinition) beanFactory.getBeanDefinition("memberServer");
        // 用context.getBean(UserService.class)拿UserService对象
        // 修改memberDefinition的Bean类   
        memberDefinition.setBeanClass(UserService.class);
    }
}

     我们只是把MemberService交给Spring进行管理,而UserService并没有。但是由于我们通过BeanFactoryPostProcessor来干涉Bean的创建,造成的结果是:    

// 不可以取到MemberService的bean对象
context.getBean(MemberService.class);   
// 可以取到UserService的bean对象
context.getBean(UserService.class);  

● BeanFactoryPostProcessor执行时机

    在第一篇的推文中有写到,AnnotationConfigApplicationContext的构造器会调用refresh的方法。这一个方法可以说是Spring中最重要的方法了。我们不得不来研究它里面做了些什么事情。

public void refresh() throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
        //准备工作包括设置启动时间,是否激活标识位
        this.prepareRefresh();
        //返回一个bean工厂
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        //准备工厂
        this.prepareBeanFactory(beanFactory);
        try {
            //这个方法在当前版本是没有代码的,
            this.postProcessBeanFactory(beanFactory);
            //在spring的环境中去执行已经被注册的factory Processors
            //设置执行自定义的ProcessBeanFactory和spring内部自己定义ProcessBeanFactory
            //重要用来扫描并且注册到我们beanDefinitionMap中
            //beanDefinitionNames也有存上一份
            this.invokeBeanFactoryPostProcessors(beanFactory);
            //注册beanPostProcessor
            this.registerBeanPostProcessors(beanFactory);
            this.initMessageSource();
            this.initApplicationEventMulticaster();
            this.onRefresh();
            this.registerListeners();
            //实例化bean的方法
            //里面调用beanFactory.preInstantiateSingletons()实例化
            this.finishBeanFactoryInitialization(beanFactory);
            this.finishRefresh();
        } catch (BeansException var9) {
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling       refresh attempt: " + var9);
            }
            this.destroyBeans();
            this.cancelRefresh(var9);
            throw var9;
        } finally {
            this.resetCommonCaches();
        }
    }
}

        在this.invokeBeanFactoryPostProcessors(beanFactory)执行前的beandefinitionMap的数据,有6个是spring在此前自己注册的,还有一个是我们的java配置类。spring注册的处理器主要是根据java配置类的规则,判断出那些类要交给Spring产生Bean对象。把那些符合规则的类,生成一个BeanDefinition对象,存进beandefinitionMap里面,并且在beanDefinitionNames也存放它的名字。

    而我们自己写的BeanFactoryPostProcesssor是在Spring自己的Processor执行完后在执行的,因为Spring的那些执行完,才可以取得到我们那些带@Component的类。

● 有图有真相

this.invokeBeanFactoryPostProcessors(beanFactory)执行前的断点图

this.invokeBeanFactoryPostProcessors(beanFactory)执行后的断点图

   finishBeanFactoryInitialization(beanFactory)方法的作用是创建出Bean的,而那些BeanFactoryPostProcessor是在他之前执行的。那么我们就可以通过改变beandefinitionMap存放的信息,最终改变创建出来的Bean。

专注分享Java技术,跟我一起学习吧

长按识别二维码关注

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值