Spring部分源码浅析

Spring容器中的一些组件:

  • BeanPostProcessor:bean的后置处理器,创建对象初始化前后进行拦截工作。

通过实现BeanPostProcessor接口在bean的初始化前后进行一些操作。

// 将后置处理器加入到容器
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization" + "=>" + beanName + "=>" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization" + "=>" + beanName + "=>" + bean);
        return bean;
    }
}

给两个方法打上断点,我们来调试。
查看方法调用栈:
在这里插入图片描述
bean的第一次创建是采用createBean,又由于createBean调用了doCreateBean,所以我们直接进入doCreateBean方法。
在这里插入图片描述
populateBean是对bean的属性进行赋值,然后再调用initializeBean。我们进入initializeBean。
在这里插入图片描述

  1. applyBeanPostProcessBeforeInitialization:循环遍历得到容器中所有的beanPostProcessor并执行postProcessBeforeInitialization。
  2. invokeInitMethods:执行自定义初始化方法。
  3. applyBeanPostProcessAfterInitialization:该方法作用同applyBeanPostProcessBeforeInitialization。
  • Spring底层对BeanPostProcessor的使用:

如果我们要在Dog中使用到容器,我们可以实现ApplicationContextAware接口,然后将该容器传入。那么在dog实例创建的时候,是如何知道该bean是否实现了ApplicationContextAware接口呢?那就是通过ApplicationContextAwareProcessor
在这里插入图片描述
可以看到,在ApplicationContextAwareProcessor的postProcessBeforeInitialization方法中,判断了bean实例是否为ApplicationContextAware的实现类,如果是,则调用相应的方法(invokeAwareInterface)注入值。
在这里插入图片描述
在这里插入图片描述
@Autowired,@PostConstruct,@PreDestroy,bean的赋值,生命周期的注解功能等等,都用到了BeanPostProcessor…

  • BeanFactoryPostProcessor:BeanFactory的后置处理器

在BeanFactory标准初始化之后调用,即beanFactory已经保存所有的bean定义,但bean实例还未创建。

写我们自己的BeanFactoryPostProcessor:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanFactoryPostProcessor->postProcessBeanFactory...");
        int count = beanFactory.getBeanDefinitionCount();
        String[] names = beanFactory.getBeanDefinitionNames();
        System.out.println(count);
        System.out.println(Arrays.asList(names));
    }
}

给postProcessBeanFactory方法打上断点,我们来调试,查看什么时候执行BeanFactoryPostProcessors。
在refresh中可以看到:
在这里插入图片描述
而初始化方法在这之后执行,所以我们通过源码验证了BeanFactory的后置处理器在BeanFactory标准初始化之后调用
从bean工厂中加载所有的BeanFactoryPostProcessor:
在这里插入图片描述
有优先级的基础上,分别排序,执行排过序的BeanFactoryPostProcessors。如果没有分类的话,那么会发生某个bean依赖另外一个bean创建失败的情况。
在这里插入图片描述
没有优先级的在这里执行:
在这里插入图片描述
具体的执行方法:遍历出所有的后置处理器并调用相应的方法。
在这里插入图片描述
分别实现了BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean,BeanPostProcessor,BeanFactoryPostProcessor接口后,各个方法的执行顺序…
在这里插入图片描述

  • BeanDefinitionRegistryPostProcessor:在bean的定义信息将要被加载(还未加载),但bean实例还未创建的时候执行。

BeanDefinitionRegistry:bean定义信息的保存中心,BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息创建bean实例的。
优先于BeanFactoryPostProcessor执行,利用BeanDefinitionRegistryPostProcessor给容器中额外注册组件。

/* 此方法优先于postProcessBeanFactory()执行 */
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
     System.out.println("postProcessBeanDefinitionRegistry...bean的数量:" + registry.getBeanDefinitionCount());
     // 注册bean定义
     RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class);
    // 或者AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Blue.class).getBeanDefinition();
     registry.registerBeanDefinition("hello",beanDefinition);
}

BeanDefinitionRegistry后置处理器优先于BeanFactory后置处理执行。
在这里插入图片描述

  • ApplicationListener:监听容器中发布的事件,进行事件开发。
    自定义事件监听器步骤:
  1. 写一个监听器来监听某事件(ApplicationEvent此类型的事件
  2. 把监听器加入到容器
  3. 容器中有相应类型事件(ApplicationEvent)的发布,就能被我们监听到
    ContextRefreshedEvent:容器创建完成(所有bean都创建)会发布此事件
    ContextClosedEvent:容器关闭会发布此事件

ioc容器的创建过程ClassPathXmlApplicationContext为例

note:使用注解创建spring容器的话,beanFactory在GenericApplicationContext中实例化

public GenericApplicationContext() {
	this.beanFactory = new DefaultListableBeanFactory();
}

在这里插入图片描述
可以看到该构造器调用了参数configLocations为数组类型的构造器,即可以传入多个的spring文件,并且设置refresh为true。
在这里插入图片描述
调用了父类的空参构造器,
AbstractXmlApplicationContext->
AbstractRefreshableConfigApplicationContext->
AbstractRefreshableApplicationContext->
AbstractApplicationContext
最终来到这里,我们进去看看到底它要做什么
在这里插入图片描述
可以发现,在这里面对spring容器的属性进行一些设置…
在这里插入图片描述
如果父环境是非空且其环境是ConfigurableEnvironment的实例,则将父环境与此(子)应用程序上下文环境合并。
在这里插入图片描述
以上是 super(parent); 的调用过程,接下来看看 setConfigLocations(configLocations);
设置此应用程序上下文的配置位置。如果没有设置,则实现可以适当地使用默认值。
在这里插入图片描述
因为我只写了一个spring配置文件,所以可以看到configLocations的参数列表只有一个,配置文件以数组的形式存储。
在这里插入图片描述
接下来进入refresh,可以发现该方法被synchronized修饰,即该方法是同步的。
在这里插入图片描述
以下为refresh中调用的方法

进入prepareRefresh
prepareRefresh:对之前定义的属性进行初始化,如设置上下文的启动时间…
在这里插入图片描述
initPropertySources:该方法什么也没做(maybe)…留下的注释是默认什么都不做?让子类去实现?我们可以在子类中重写该方法。
在这里插入图片描述
该方法的作用暂时不清楚…
涉及到的类和方法:ConfigurableEnvironment,public void validateRequiredProperties()…
在这里插入图片描述
接下来对上下文的监听器进行设置…具体还没弄清楚…
在这里插入图片描述
进入obtainFreshBeanFactory:刷新bean factory

如果存在之前的beanFactory则关闭,并为该上下文创建一个新的beanFactory(DefaultListableBeanFactory)。
在这里插入图片描述
进入prepareBeanFactory:配置bean factory,例如context’s ClassLoader and post-processors

进入invokeBeanFactoryPostProcessors:实例化并调用所有注册的BeanFactoryPostProcessor bean,必须在单例的bean之前调用

进入initApplicationEventMulticaster:初始化事件多播器(派发器),监听的事件存在于此。

进入onRefresh:在特定的上下文子类中初始化其他特殊的bean

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值