美文网首页java编程/提升
spring源码解析---spring-core(三)

spring源码解析---spring-core(三)

作者: 程序员ken | 来源:发表于2020-07-25 21:24 被阅读0次

    getBean

    • 这里便是bean初始化的核心逻辑。源码比较复杂,分开说。以getBean(String name)为例。AbstractBeanFactory.getBean:

    • @Overridepublic Object getBean(String name) throws BeansException {

      return doGetBean(name, null, null, false);

      }

    • 第二个参数表示bean的Class类型,第三个表示创建bean需要的参数,最后一个表示不需要进行类型检查。

    beanName转化

    • final String beanName = transformedBeanName(name);

    • 这里是将FactoryBean的前缀去掉以及将别名转为真实的名字。

    手动注册bean检测

    • 前面注册环境一节说过,Spring其实手动注册了一些单例bean。这一步就是检测是不是这些bean。如果是,那么再检测是不是工厂bean,如果是返回其工厂方法返回的实例,如果不是返回bean本身。

    • Object sharedInstance = getSingleton(beanName);

      if (sharedInstance != null && args == null) {

      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

      }

    检查父容器

    • 如果父容器存在并且存在此bean定义,那么交由其父容器初始化:

    • BeanFactory parentBeanFactory = getParentBeanFactory();

      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {

      // Not found -> check parent.

      //此方法其实是做了前面beanName转化的逆操作,因为父容器同样会进行转化操作

      String nameToLookup = originalBeanName(name);

      if (args != null) {

      // Delegation to parent with explicit args.

      return (T) parentBeanFactory.getBean(nameToLookup, args);

      } else {

      // No args -> delegate to standard getBean method.

      return parentBeanFactory.getBean(nameToLookup, requiredType);

      }

      }

    依赖初始化

    • bean可以由depends-on属性配置依赖的bean。Spring会首先初始化依赖的bean。

    • String[] dependsOn = mbd.getDependsOn();

      if (dependsOn != null) {

      for (String dependsOnBean : dependsOn) {

      //检测是否存在循环依赖

      if (isDependent(beanName, dependsOnBean)) {

      throw new BeanCreationException(mbd.getResourceDescription(), beanName,

      "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");

      }

      registerDependentBean(dependsOnBean, beanName);

      getBean(dependsOnBean);

      }

      }

    • registerDependentBean进行了依赖关系的注册,这么做的原因是Spring在即进行bean销毁的时候会首先销毁被依赖的bean。依赖关系的保存是通过一个ConcurrentHashMap<String, Set>完成的,key是bean的真实名字。

    Singleton初始化

    • 虽然这里大纲是Singleton初始化,但是getBean方法本身是包括所有scope的初始化,在这里一次说明了。

    • if (mbd.isSingleton()) {

      sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {

      @Override

      public Object getObject() throws BeansException {

      return createBean(beanName, mbd, args);

      }

      });

      bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

      }

    getSingleton方法

    是否存在

    • 首先会检测是否已经存在,如果存在,直接返回:

    • synchronized (this.singletonObjects) {

      Object singletonObject = this.singletonObjects.get(beanName);

      }

    • 所有的单例bean都保存在这样的数据结构中:ConcurrentHashMap<String, Object>。

    bean创建

    • 源码位于AbstractAutowireCapableBeanFactory.createBean,主要分为几个部分:
    lookup-method检测
    • 此部分用于检测lookup-method标签配置的方法是否存在:

    • RootBeanDefinition mbdToUse = mbd;

      mbdToUse.prepareMethodOverrides();

    • prepareMethodOverrides:

    • public void prepareMethodOverrides() throws BeanDefinitionValidationException {

      // Check that lookup methods exists.

      MethodOverrides methodOverrides = getMethodOverrides();

      if (!methodOverrides.isEmpty()) {

      Set<MethodOverride> overrides = methodOverrides.getOverrides();

      synchronized (overrides) {

      for (MethodOverride mo : overrides) {

      prepareMethodOverride(mo);

      }

      }

      }

      }

    • prepareMethodOverride:

    • protected void prepareMethodOverride(MethodOverride mo) {

      int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());

      if (count == 0) {

      throw new BeanDefinitionValidationException(

      "Invalid method override: no method with name '" + mo.getMethodName() +

      "' on class [" + getBeanClassName() + "]");

      } else if (count == 1) {

      // Mark override as not overloaded, to avoid the overhead of arg type checking.

      mo.setOverloaded(false);

      }

      }

    InstantiationAwareBeanPostProcessor触发
    • 在这里触发的是其postProcessBeforeInitialization和postProcessAfterInstantiation方法。

    • Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

      if (bean != null) {

      return bean;

      }

      Object beanInstance = doCreateBean(beanName, mbdToUse, args);

      return beanInstance;

    • 继续:

    • protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {

      Object bean = null;

      if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {

      // Make sure bean class is actually resolved at this point.

      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {

      Class<?> targetType = determineTargetType(beanName, mbd);

      if (targetType != null) {

      bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);

      if (bean != null) {

      bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);

      }

      }

      }

      mbd.beforeInstantiationResolved = (bean != null);

      }

      return bean;

      }

    • 从这里可以看出,如果InstantiationAwareBeanPostProcessor返回的不是空,那么将不会继续执行剩下的Spring初始化流程,此接口用于初始化自定义的bean,主要是在Spring内部使用。

    doCreateBean
    • 同样分为几部分。
    创建(createBeanInstance)
    • 关键代码:

    • BeanWrapper instanceWrapper = null;

      if (instanceWrapper == null) {

      instanceWrapper = createBeanInstance(beanName, mbd, args);

      }

    • createBeanInstance的创建过程又分为以下几种情况:

    • 工厂bean:

      调用instantiateUsingFactoryMethod方法:

      protected BeanWrapper instantiateUsingFactoryMethod(

      String beanName, RootBeanDefinition mbd, Object[] explicitArgs) {

      return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);

      }

      注意,此处的工厂bean指的是配置了factory-bean/factory-method属性的bean,不是实现了FacrotyBean接口的bean。如果没有配置factory-bean属性,那么factory-method指向的方法必须是静态的。此方法主要做了这么几件事:

    • 初始化一个BeanWrapperImpl对象。

    • 根据设置的参数列表使用反射的方法寻找相应的方法对象。

    • InstantiationStrategy:

      bean的初始化在此处又抽成了策略模式,类图:

      instantiateUsingFactoryMethod部分源码:

      beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(

      mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);

      getInstantiationStrategy返回的是CglibSubclassingInstantiationStrategy对象。此处instantiate实现也很简单,就是调用工厂方法的Method对象反射调用其invoke即可得到对象,SimpleInstantiationStrategy.

      instantiate核心源码:

      @Overridepublic Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,

      Object factoryBean, final Method factoryMethod, Object... args) {

      return factoryMethod.invoke(factoryBean, args);

      }

    • 构造器自动装配

      createBeanInstance部分源码:

      // Need to determine the constructor...Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

      if (ctors != null ||

      mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||

      //配置了<constructor-arg>子元素

      mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {

      return autowireConstructor(beanName, mbd, ctors, args);

      }

      determineConstructorsFromBeanPostProcessors源码:

      protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(Class<?> beanClass, String beanName) {

      if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {

      for (BeanPostProcessor bp : getBeanPostProcessors()) {

      if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {

      SmartInstantiationAwareBeanPostProcessor ibp =

      (SmartInstantiationAwareBeanPostProcessor) bp;

      Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);

      if (ctors != null) {

      return ctors;

      }

      }

      }

      }

      return null;

      }

      可见是由SmartInstantiationAwareBeanPostProcessor决定的,默认是没有配置这种东西的。

      之后就是判断bean的自动装配模式,可以通过如下方式配置:

      <bean id="student" class="base.Student" primary="true" autowire="default" />

      autowire共有以下几种选项:

    • no: 默认的,不进行自动装配。在这种情况下,只能通过ref方式引用其它bean。

    • byName: 根据bean里面属性的名字在BeanFactory中进行查找并装配。

    • byType: 按类型。

    • constructor: 以byType的方式查找bean的构造参数列表。

    • default: 由父bean决定。

    • 得到合适的构造器对象。

    • 根据构造器参数的类型去BeanFactory查找相应的bean:

      入口方法在ConstructorResolver.resolveAutowiredArgument:

      protected Object resolveAutowiredArgument(

      MethodParameter param, String beanName, Set<String> autowiredBeanNames,

      TypeConverter typeConverter) {

      return this.beanFactory.resolveDependency(

      new DependencyDescriptor(param, true), beanName,

      autowiredBeanNames, typeConverter);

      }

    • 最终调用的还是CglibSubclassingInstantiationStrategy.instantiate方法,关键源码:

    • @Overridepublic Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,

      final Constructor<?> ctor, Object... args) {

      if (bd.getMethodOverrides().isEmpty()) {

      //反射调用

      return BeanUtils.instantiateClass(ctor, args);

      } else {

      return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);

      }

      }

    • 可以看出,如果配置了lookup-method标签,得到的实际上是用Cglib生成的目标类的代理子类。

    • CglibSubclassingInstantiationStrategy.instantiateWithMethodInjection:

    • @Overrideprotected Object instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner,Constructor<?> ctor, Object... args) {

      // Must generate CGLIB subclass...

      return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);

      }

    • 默认构造器

      一行代码,很简单:

      // No special handling: simply use no-arg constructor.return instantiateBean(beanName, mbd);

    MergedBeanDefinitionPostProcessor
    • 触发源码:

    • synchronized (mbd.postProcessingLock) {

      if (!mbd.postProcessed) {

      applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

      mbd.postProcessed = true;

      }

      }

    • 此接口也是Spring内部使用的,不管它了。

    属性解析
    • 入口方法: AbstractAutowireCapableBeanFactory.populateBean,它的作用是: 根据autowire类型进行autowire by name,by type 或者是直接进行设置,简略后的源码:

    • protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {

      //所有<property>的值

      PropertyValues pvs = mbd.getPropertyValues();

    if (mbd.getResolvedAutowireMode() \== RootBeanDefinition.AUTOWIRE\_BY\_NAME ||
    
    mbd.getResolvedAutowireMode() \== RootBeanDefinition.AUTOWIRE\_BY\_TYPE) {
    
    MutablePropertyValues newPvs \= new MutablePropertyValues(pvs);
    
      
    
    // Add property values based on autowire by name if applicable.
    
    if (mbd.getResolvedAutowireMode() \== RootBeanDefinition.AUTOWIRE\_BY\_NAME) {
    
    autowireByName(beanName, mbd, bw, newPvs);
    
    }
    
      
    
    // Add property values based on autowire by type if applicable.
    
    if (mbd.getResolvedAutowireMode() \== RootBeanDefinition.AUTOWIRE\_BY\_TYPE) {
    
    autowireByType(beanName, mbd, bw, newPvs);
    
    }
    
      
    
    pvs \= newPvs;
    
    }
    
    //设值
    
    applyPropertyValues(beanName, mbd, bw, pvs);
    
    }
    
    • autowireByName源码:

    • protected void autowireByName(

      String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

      //返回所有引用(ref="XXX")的bean名称

      String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);

      for (String propertyName : propertyNames) {

      if (containsBean(propertyName)) {

      //从BeanFactory获取

      Object bean = getBean(propertyName);

      pvs.add(propertyName, bean);

      registerDependentBean(propertyName, beanName);

      }

      }

      }

    • autowireByType也是同样的套路,所以可以得出结论:autowireByName和autowireByType方法只是先获取到引用的bean,真正的设值是在applyPropertyValues中进行的。

    属性设置
    • Spring判断一个属性可不可以被设置(存不存在)是通过java bean的内省操作来完成的,也就是说,属性可以被设置的条件是此属性拥有public的setter方法,并且注入时的属性名应该是setter的名字。
    初始化
    • 此处的初始化指的是bean已经构造完成,执行诸如调用其init方法的操作。相关源码:

    • // Initialize the bean instance.Object exposedObject = bean;

      try {

      populateBean(beanName, mbd, instanceWrapper);

      if (exposedObject != null) {

      exposedObject = initializeBean(beanName, exposedObject, mbd);

      }

      }

    • initializeBean:

    • protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {

      if (System.getSecurityManager() != null) {

      AccessController.doPrivileged(new PrivilegedAction<Object>() {

      @Override

      public Object run() {

      invokeAwareMethods(beanName, bean);

      return null;

      }

      }, getAccessControlContext());

      }

      else {

      invokeAwareMethods(beanName, bean);

      }

    Object wrappedBean \= bean;
    
    if (mbd \== null || !mbd.isSynthetic()) {
    
    wrappedBean \= applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    
    }
    
      
    
    invokeInitMethods(beanName, wrappedBean, mbd);
    
      
    
    if (mbd \== null || !mbd.isSynthetic()) {
    
    wrappedBean \= applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    
    }
    
    return wrappedBean;
    
    }
    
    • 主要的操作步骤一目了然。

    • Aware方法触发:

      我们的bean有可能实现了一些XXXAware接口,此处就是负责调用它们:

      private void invokeAwareMethods(final String beanName, final Object bean) {

      if (bean instanceof Aware) {

      if (bean instanceof BeanNameAware) {

      ((BeanNameAware) bean).setBeanName(beanName);

      }

      if (bean instanceof BeanClassLoaderAware) {

      ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());

      }

      if (bean instanceof BeanFactoryAware) {

      ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);

      }

      }

      }

    • BeanPostProcessor触发,没什么好说的

    • 调用init方法:

      在XML配置中,bean可以有一个init-method属性来指定初始化时调用的方法。从原理来说,其实就是一个反射调用。不过注意这里有一个InitializingBean的概念。

      此接口只有一个方法:

      void afterPropertiesSet() throws Exception;

      如果我们的bean实现了此接口,那么此方法会首先被调用。此接口的意义在于: 当此bean的所有属性都被设置(注入)后,给bean一个利用现有属性重新组织或是检查属性的机会。感觉和init方法有些冲突,不过此接口在Spring被广泛使用。

    getObjectForBeanInstance

    • 位于AbstractBeanFactory,此方法的目的在于如果bean是FactoryBean,那么返回其工厂方法创建的bean,而不是自身。

    Prototype初始化

    • AbstractBeanFactory.doGetBean相关源码:

    • else if (mbd.isPrototype()) {

      // It's a prototype -> create a new instance.

      Object prototypeInstance = null;

      try {

      beforePrototypeCreation(beanName);

      prototypeInstance = createBean(beanName, mbd, args);

      }

      finally {

      afterPrototypeCreation(beanName);

      }

      bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);

      }

    beforePrototypeCreation

    • 此方法用于确保在同一时刻只能有一个此bean在初始化。

    createBean

    • 和单例的是一样的,不在赘述。

    afterPrototypeCreation

    • 和beforePrototypeCreation对应的,你懂的。

    总结

    • 可以看出,初始化其实和单例是一样的,只不过单例多了一个是否已经存在的检查。

    其它Scope初始化

    • 其它就指的是request、session。此部分源码:

    • else {

      String scopeName = mbd.getScope();

      final Scope scope = this.scopes.get(scopeName);

      if (scope == null) {

      throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");

      }

      Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {

      @Override

      public Object getObject() throws BeansException {

      beforePrototypeCreation(beanName);

      try {

      return createBean(beanName, mbd, args);

      }

      finally {

      afterPrototypeCreation(beanName);

      }

      }

      });

      bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);

      }

    • scopes是一个LinkedHashMap<String, Scope>,可以调用 ConfigurableBeanFactory定义的registerScope方法注册其值。

    • Scope接口继承体系:

    根据socpe.get的注释,此方法如果找到了叫做beanName的bean,那么返回,如果没有,将调用ObjectFactory创建之。Scope的实现参考类图.

    本文来源于:宋文超super,专属平台有csdn、思否(SegmentFault)、 简书、 开源中国(oschina),转载请注明出处。

    相关文章

      网友评论

        本文标题:spring源码解析---spring-core(三)

        本文链接:https://www.haomeiwen.com/subject/thzmlktx.html