Spring IoC 容器工作流程图:

IoC 容器创建 Bean 对象的流程图

初始化 & 实例化 的不同概念

类的实例化类的初始化 在 Spring 中是不同的细分概念。

image-20201116202551392

IoC 容器创建 Bean 的相关核心类:

BeanDefinition

什么是 BeanDefinition

可以看到 其位于 org.springframework.beans.factory.config 包中,是一个接口。

image-20201116200541241

类注释:

A BeanDefinition describes a bean instance, which has property values, constructor argument values, and further information supplied by concrete implementations.
This is just a minimal interface: The main intention is to allow a BeanFactoryPostProcessor to introspect and modify property values and other bean metadata.

BeanDefinition 描述了 bean实例的 「字段信息」,「构造函数的值」 ,以及具体的实现方式。

这个接口是最简单的接口, 主要目的是允许 BeanFactoryPostProcessor 内省修改属性值和其他 bean 元数据。

这里的 BeanPostProcessor 就是对类的后置处理器,使用了 AOP 动态的对类进行增强,后面会详细来讲。

Spring 官方文档中对 BeanDefinition 的描述如下:

BeanDefinition 包含的 bean 元数据包括:

  • 全限定路径的类名(package-qualified class name) 作用是通过反射+全限定类名就可以直接构造类的实例。
  • Bean 行为配置元素(Bean behavioral configuration elements) ,用来声明 Bean作用域生命周期回调 等。
  • Bean 中依赖的其他 Bean , 也就是循环依赖的解决。
  • 其他配置设置,例如 池的大小限制或者在管理连接池的 bean 中要使用的连接数 —— 也就是 bean 对应属性的初始化。

BeanDefinitionReader

org.springframework.beans.factory.support.BeanDefinitionReader , 作用是用来读取 Bean 的定义信息,包名也可以看出来是起一个支持的作用,属于 BeanDefinition 的配套设施。

BeanFactory

IoC 容器的底层接口,最基础的 IoC 容器,非常重要。"The root interface for accessing a Spring bean container."

BeanFactory 中定义了很多关键的方法,比如 getBean

image-20201116202931792

BeanFactoryPostProcessor

  • 处理 Bean 的定义信息

PlaceholderConfigurerSupport

  • BeanFactoryPostProcessoru 的具体实现子类。

作用:XML 中定义的 Bean 中定义的占位符进行 替换,例如:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"/>
     <property name="driverClassName" value="${driver}"/>
     <property name="url" value="jdbc:${dbname}"/>
   </bean>

上面定义的 ${driver} 和 jdbc:${dbname} 会在这个类中被处理,替换为具体的值。

BeanPostProcessor

  • 作用:处理 Bean 对象的信息,包括两个方面:
    • 实例化
    • 初始化

类中的两个方法:

  • postProcessBeforeInitialization —— 前置
  • postProcessAfterInitialization —— 后置

上面这两个方法使用的就是 AOP , 下面去找一下具体的实现地方。

image-20201116222030496

// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                             @Nullable Object[] specificInterceptors, TargetSource targetSource) {

  if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
    AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
  }

  ProxyFactory proxyFactory = new ProxyFactory();
  proxyFactory.copyFrom(this);

  if (!proxyFactory.isProxyTargetClass()) {
    if (shouldProxyTargetClass(beanClass, beanName)) {
      proxyFactory.setProxyTargetClass(true);
    }
    else {
      evaluateProxyInterfaces(beanClass, proxyFactory);
    }
  }

  Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  proxyFactory.addAdvisors(advisors);
  proxyFactory.setTargetSource(targetSource);
  customizeProxyFactory(proxyFactory);

  proxyFactory.setFrozen(this.freezeProxy);
  if (advisorsPreFiltered()) {
    proxyFactory.setPreFiltered(true);
  }
  // 生成代理对象
  return proxyFactory.getProxy(getProxyClassLoader());
}

下一步:

// org.springframework.aop.framework.ProxyFactory
public Object getProxy(@Nullable ClassLoader classLoader) {
  // 这里点进去查看 createAopProxy 的源码,就是具体生成代理对象的地方
  return createAopProxy().getProxy(classLoader);
}

点进 createAopProxy

// org.springframework.aop.framework.ProxyCreatorSupport	
protected final synchronized AopProxy createAopProxy() {
  if (!this.active) {
    activate();
  }
  return getAopProxyFactory().createAopProxy(this);
}

点开 createAopProxy

// org.springframework.aop.framework.AopProxyFactory
public interface AopProxyFactory {
  AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}

可以看到来到了一个接口,接下来找到实现类:DefaultAopProxyFactory

// org.springframework.aop.framework.DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
    Class<?> targetClass = config.getTargetClass();
    if (targetClass == null) {
      throw new AopConfigException("TargetSource cannot determine target class: " +
                                   "Either an interface or a target is required for proxy creation.");
    }
    if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {			
      // JDK 的 AOP 代理实现
      return new JdkDynamicAopProxy(config);
    }
    // CGLIB 的 AOP 代理实现
    return new ObjenesisCglibAopProxy(config);
  }
  else {
    return new JdkDynamicAopProxy(config);
  }
}

到这里,我们找到了创建 Spring 中创建 AOP 代理的具体位置,并且看到了两种不同的创建技术 : JDKCGLIB

那么问题来了,这里我是跟着教学找的,我们如果自己去找 postProcessAfterInitialization ,方法该怎样找呢?

点开 postProcessAfterInitialization 找其对应的实现,可以看到有这么多类,至于怎样选中我们要找的 AbstractAutoProxyCreator,暂时也没有思路

image-20201116223914410

// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator 中对应的 postProcessAfterInitialization 实现

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  if (bean != null) {
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    if (this.earlyProxyReferences.remove(cacheKey) != bean) {
      // 跳转到 wrapIfNecessary 里
      return wrapIfNecessary(bean, beanName, cacheKey); 
    }
  }
  return bean;
}

// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator 

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    return bean;
  }
  if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    return bean;
  }
  if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
  }

  // Create proxy if we have advice.
  Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  if (specificInterceptors != DO_NOT_PROXY) {
    this.advisedBeans.put(cacheKey, Boolean.TRUE);
    // createProxy 就来到了具体创建代理的地方入口,也就找到了 Proxy 创建的地方
    Object proxy = createProxy (
      bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    this.proxyTypes.put(cacheKey, proxy.getClass());
    return proxy;
  }

  this.advisedBeans.put(cacheKey, Boolean.FALSE);
  return bean;
}

Spring 中 Bean 生命周期 —— 创建部分

完整的 Bean 生命周期:(来自 BeanFactory 中的注释)

关键方法 AbstractApplicationContext#refresh()

Environment

image-20201117005906665

  • 获取当前系统的环境变量/属性值
    • System.getenv()
    • System.getProperties()

具体子类实现:「StandardEnvironment

//  org.springframework.core.env.StandardEnvironment
// 但是其实这里 StandardEnvironment 继承的是 AbstractEnvironment 中的实现
// StandardEnvironment 并没有 override 下面两个方法

public Map<String, Object> getSystemEnvironment() {
  if (suppressGetenvAccess()) {
    return Collections.emptyMap();
  }
  try {
    return (Map) System.getenv();
  }
  catch (AccessControlException ex) {
    return (Map) new ReadOnlySystemAttributesMap() {
      @Override
      protected String getSystemAttribute(String attributeName) {
        try {
          return System.getenv(attributeName);
        }
        catch (AccessControlException ex) {
          if (logger.isInfoEnabled()) {
            logger.info("Caught AccessControlException when accessing system environment variable '" +
                        attributeName + "'; its value will be returned [null]. Reason: " + ex.getMessage());
          }
          return null;
        }
      }
    };
  }
}

public Map<String, Object> getSystemProperties() {
  try {
    return (Map) System.getProperties();
  }
  catch (AccessControlException ex) {
    return (Map) new ReadOnlySystemAttributesMap() {
      @Override
      protected String getSystemAttribute(String attributeName) {
        try {
          return System.getProperty(attributeName);
        }
        catch (AccessControlException ex) {
          if (logger.isInfoEnabled()) {
            logger.info("Caught AccessControlException when accessing system property '" +
                        attributeName + "'; its value will be returned [null]. Reason: " + ex.getMessage());
          }
          return null;
        }
      }
    };
  }
}

需求:在 bean 对象创建过程中,需要详细了解每个步骤完成的进度,不同阶段做对应的不同处理工作,例如:

  • bean 实例化完成后 触发对应事件
  • 填充属性完成后 触发对应事件
  • 执行 bean init 方法 之后 触发对应事件

观察者模式:监听器、监听事件。

思路: 提前准备好监听器,当 bean 触发事件之后回调对应的监听器。

参考资料:

马士兵Spring源码讲解

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

最是人间留不住,曾是惊鸿照影来。