Spring源码解析:Spring Aware 原理解析

缺乏、安全感 2022-02-01 00:37 405阅读 0赞

写在前面

Spring源码解析系列文章是我最近在学习了一段Spring,SpringBoot和SpringMVC等一系列的源码后整理的文章。我会随着我对Spring的理解来进行相应的文章的整合和归纳。

我决定从提出一个问题开始。然后围绕着解决这个问题的方式来剖析源码。当我们把一个问题搞懂了的时候。里面的源码我们也就清楚了。事实上看源码不是目标。解决一些日常的困惑才是目标。

问题

为什么被Spring管理的类。只要实现了Aware接口。Spring就会自动把对应的对象注入进来。这个bean如果想要使用直接使用就可以了。如下: Spring会自动把ApplicationContext注入到AwareTest这个bean里面。

  1. public class AwareTest implements ApplicationContextAware {
  2. public ApplicationContext applicationContext;
  3. @Override
  4. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  5. this.applicationContext = applicationContext;
  6. }
  7. public void checkAware(){
  8. if(applicationContext != null){
  9. System.out.println("ApplicationContext inject success");
  10. }
  11. }
  12. }

源码解析:

  1. 我们都知道在AbstractApplicationContext里面真正的启动ApplicationContext的函数是refresh()方法。具体的方法如下

    public void refresh() throws BeansException, IllegalStateException {

    1. synchronized (this.startupShutdownMonitor) {
    2. // Prepare this context for refreshing.
    3. prepareRefresh();
    4. // Tell the subclass to refresh the internal bean factory.
    5. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    6. // Prepare the bean factory for use in this context.
    7. prepareBeanFactory(beanFactory);
    8. try {
    9. // Allows post-processing of the bean factory in context subclasses.
    10. postProcessBeanFactory(beanFactory);
    11. // Invoke factory processors registered as beans in the context.
    12. invokeBeanFactoryPostProcessors(beanFactory);
    13. // Register bean processors that intercept bean creation.
    14. registerBeanPostProcessors(beanFactory);
    15. // Initialize message source for this context.
    16. initMessageSource();
    17. // Initialize event multicaster for this context.
    18. initApplicationEventMulticaster();
    19. // Initialize other special beans in specific context subclasses.
    20. onRefresh();
    21. // Check for listener beans and register them.
    22. registerListeners();
    23. // Instantiate all remaining (non-lazy-init) singletons.
    24. finishBeanFactoryInitialization(beanFactory);
    25. // Last step: publish corresponding event.
    26. finishRefresh();
    27. }
    28. catch (BeansException ex) {
    29. if (logger.isWarnEnabled()) {
    30. logger.warn("Exception encountered during context initialization - " +
    31. "cancelling refresh attempt: " + ex);
    32. }
    33. // Destroy already created singletons to avoid dangling resources.
    34. destroyBeans();
    35. // Reset 'active' flag.
    36. cancelRefresh(ex);
    37. // Propagate exception to caller.
    38. throw ex;
    39. }
    40. finally {
    41. // Reset common introspection caches in Spring's core, since we
    42. // might not ever need metadata for singleton beans anymore...
    43. resetCommonCaches();
    44. }
    45. }
    46. }
  2. 可以看到有一个prepareBeanFactory的方法,我们再往里面看一下这个方法里面究竟有什么。可以发现给BeanFactory添加了一个BeanPostProcessor。名字是ApplicationContextAwareProcessor

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {

    1. // Tell the internal bean factory to use the context's class loader etc.
    2. beanFactory.setBeanClassLoader(getClassLoader());
    3. beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    4. beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    5. // Configure the bean factory with context callbacks.
    6. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    7. beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    8. ... 多余的代码不贴出来了

    }

  3. BeanPostProcessor这个接口我们都很熟悉了。我们看一下这个里面PostProcessBeforeInitialization()函数。传入bean和beanName。最后是调用了invokeAwareInterfaces(bean)这个函数。如果bean 是aware类的子类。那么就调用bean的set方法将ApplicationContext塞到bean里面。然后业务代码在需要使用ApplicationContext的时候就可以直接使用了。因为已经被set进来了。

    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {

    1. AccessControlContext acc = null;
    2. if (System.getSecurityManager() != null &&
    3. (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
    4. bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
    5. bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
    6. acc = this.applicationContext.getBeanFactory().getAccessControlContext();
    7. }
    8. if (acc != null) {
    9. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    10. invokeAwareInterfaces(bean);
    11. return null;
    12. }, acc);
    13. }
    14. else {
    15. invokeAwareInterfaces(bean);
    16. }
    17. return bean;
    18. }
    19. private void invokeAwareInterfaces(Object bean) {
    20. if (bean instanceof Aware) {
    21. if (bean instanceof EnvironmentAware) {
    22. ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
    23. }
    24. if (bean instanceof EmbeddedValueResolverAware) {
    25. ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    26. }
    27. if (bean instanceof ResourceLoaderAware) {
    28. ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    29. }
    30. if (bean instanceof ApplicationEventPublisherAware) {
    31. ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    32. }
    33. if (bean instanceof MessageSourceAware) {
    34. ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    35. }
    36. if (bean instanceof ApplicationContextAware) {
    37. ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    38. }
    39. }
    40. }
  4. 我们再来看一下。Spring是什么时候调用了BeanPostProcessor的postProcessBeforeInitialization函数的。在AbstractAutowireCapableBeanFactory的initializeBean方法里面 , 在调用InvokeInitMethods的方法之前。先执行了applyBeanPost

ProcessorBeforeInitialization的方法。这个方法里面就是将所有的BeanPostProcessor的的postProcessBeforeInitialization()都执行一遍。包括之前创建的ApplicationContextAwareProcessor。于是ApplicationContextAwareProcessor这个时刻就将ApplicationContext注入到我们的Bean里面了。

  1. protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
  2. if (System.getSecurityManager() != null) {
  3. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  4. invokeAwareMethods(beanName, bean);
  5. return null;
  6. }, getAccessControlContext());
  7. }
  8. else {
  9. invokeAwareMethods(beanName, bean);
  10. }
  11. Object wrappedBean = bean;
  12. if (mbd == null || !mbd.isSynthetic()) {
  13. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  14. }
  15. try {
  16. invokeInitMethods(beanName, wrappedBean, mbd);
  17. }
  18. catch (Throwable ex) {
  19. throw new BeanCreationException(
  20. (mbd != null ? mbd.getResourceDescription() : null),
  21. beanName, "Invocation of init method failed", ex);
  22. }
  23. if (mbd == null || !mbd.isSynthetic()) {
  24. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  25. }
  26. return wrappedBean;
  27. }

上面是跟着源码走了一遍。我看完之后的理解就是。Spring在整个设计上对于这种松耦合和可插拔真是做了非常多的工作。可以说Spring 本身的ioc的代码并不复杂。大量的代码工作都是为了方便开发者自己去拓展Spring的边界。让开发者可以更好的去控制和管理bean这个对象。Spring的代码建议多读几遍。虽然每一遍读起来都很痛苦。但是每一次读都会有新的感受。

这一篇对原理的解析也还不错。参考链接

发表评论

表情:
评论列表 (有 0 条评论,405人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Spring Cloud理解

    概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术。不过大多数讲解还停留在对Spring Cloud功能使用的层面,其底层的很

    相关 Spring Cloud理解

    > 本文为转载文章,作者:中华石杉,十余年BAT架构经验,倾囊相授。作者微信公众号:石杉的架构笔记(ID:shishan100) 概述 毫无疑问,Spring Cloud是