当前位置:   article > 正文

0105bean实例化-Bean生命周期详解-spring_bean实例化阶段

bean实例化阶段

1 前言

Bean实例化分为3个阶段:前阶段、实例化阶段、后阶段,这里只讲解前2个阶段

2 BeanPostProcessor

BeanPostProcessor(Bean后置处理器)是一个接口,还有很多子接口,这些接口中提供了很多方法,spring在bean生命周期的不同阶段,会调用上面这个列表中的BeanPostProcessor中的一些方法,来对生命周期进行扩展。bean生命周期中的扩展点都是依靠BeanPostProcessor来实现的,所以如果大家想对bean的生命周期进行干预,这块一定要掌握好。

BeanPostProcessor接口是spring提供给开发者的扩展点,通过容器在Bean的生命周期的适当位置进行调用。

BeanFactory和ApplicationContext对待bean后置处理器稍有不同。ApplicationContext会自动检测在配置文件中实现了BeanPostProcessor接口的所有bean,并把它们注册为后置处理器,然后在容器创建bean的适当时候调用,因此部署一个后置处理器同部署其他的bean并没有什么区别。而使用BeanFactory实现的时候,bean 后置处理器必须通过代码显式地去注册,在IoC容器继承体系中的ConfigurableBeanFactory接口中定义了注册方法。

BeanPostProcessor对所有该注册容器中的bean生效。

不管是BeanFactory还是ApplicationContext,BeanPostProcessors后置处理器被注册后,需要有个集合存储,这个集合是AbstractBeanFactory的属性。

	/** BeanPostProcessors集合 */
	private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();

	/** post-processors缓存 */
	@Nullable
	private volatile BeanPostProcessorCache beanPostProcessorCache;

private class BeanPostProcessorCacheAwareList extends CopyOnWriteArrayList<BeanPostProcessor> {// 省略}
    
    
    static class BeanPostProcessorCache {

    final List<InstantiationAwareBeanPostProcessor> instantiationAware = new ArrayList<>();

    final List<SmartInstantiationAwareBeanPostProcessor> smartInstantiationAware = new ArrayList<>();

    final List<DestructionAwareBeanPostProcessor> destructionAware = new ArrayList<>();

    final List<MergedBeanDefinitionPostProcessor> mergedDefinition = new ArrayList<>();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

factory使用BeanPostProcessor通过BeanPostProcessorCache缓存获取,如果缓存不存在,会通过beanPostProcessors初始化缓存,在下面讲解bean实例化前阶段时,会通过源码具体了解该过程。

这里只是简单讲解了下BeanPostProcessor,为下面做铺垫,随着我们对BeanPostProcessor了解加深,我会专门写一篇关于BeanPostProcessor的内容。

和我们实例化前阶段相关的BeanPostProcessor为InstantiationAwareBeanPostProcessor。

package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.lang.Nullable;

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

   /**
    * 实例化前执行该方法
    */
   @Nullable
   default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
      return null;
   }

   /**
    *实例化之后执行该方法
    */
   default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
      return true;
   }

   /**
    * 属性赋值之前执行该方法
    */
   @Nullable
   default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
         throws BeansException {

      return pvs;
   }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

InstantiationAwareBeanPostProcessor通常用于抑制(修改)特定目标bean的默认实例化,给我们提供了三个扩展点:实例化bean之前、实例化之后、属性赋值之前。

  • postProcessBeforeInstantiation():实例化bean之前扩展点,在目标bean开始实例化前触发该方法。返回的bean对象可能是要使用的代理,而不是目标bean,从而有效地抑制了目标bean的默认实例化。如果此方法返回非null对象,则bean创建过程将被短路(也就是正常bean实例化的后续流程不再执行)。
  • postProcessAfterInstantiation():实例化后扩展点,在bean被实例化之后,通过构造函数或工厂方法。但在属性填充(from explicit properties or autowiring)发生之前,执行操作。这是在Spring的自动连接开始之前,在给定bean实例上执行自定义字段注入的理想回调。当然返回结果为true时,说明应该为bean设置属性。如果返回结果为false,跳过bean属性赋值环节。默认实现返回true。
  • postProcessProperties():在工厂将给定的属性值应用于给定的bean之前,对其进行后处理,而不需要任何属性描述符。

下面我们来看下InstantiationAwareBeanPostProcessor在实例化前阶段的该如何使用。

3 bean实例化前阶段

3.1 postProcessBeforeInstantiation()在哪里被调用?

我们还是通过getBean()方法来追踪下,在哪里回执行InstantiationAwareBeanPostProcessor。

DefaultListableBeanFactory getBean()->AbstractBeanFactory doGetBean()->AbstractAutowireCapableBeanFactory createBean()

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // 省略..
   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
  // 省略...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

resolveBeforeInstantiation() 方法

@Nullable
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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

applyBeanPostProcessorsBeforeInstantiation()方法

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
   for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
      Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
      if (result != null) {
         return result;
      }
   }
   return null;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 遍历缓存获取的InstantiationAwareBeanPostProcessor对象,实例化之前执行postProcessBeforeInstantiation()方法。

3.2 测试

自定义类MyInstantiation实现InstantiationAwareBeanPostProcessor接口。

package com.gaogzhen.myspring.processors;

import com.gaogzhen.myspring.bean.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;

/**
 * @author: Administrator
 * @createTime: 2023/03/12 09:15
 */
public class MyInstantiation implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if ("user".equalsIgnoreCase(beanClass.getSimpleName())) {
            User user = new User();
            user.setName("张三");
            return user;
        }
        return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 如果beanClass类型为User.class,我们自己new User对象,并且设置name为“张三”

测试类:

@Test
public void testInstantiation() {
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class)
            .addPropertyValue("name", "xxx");
    factory.registerBeanDefinition("user3", definitionBuilder.getBeanDefinition());
    factory.addBeanPostProcessor(new MyInstantiation());
    User user = factory.getBean("user3", User.class);
    System.out.println(user);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

测试方法中,我们设置bean的name为“xxx",看下测试结果

User{name='张三'}
  • 1
  • MyInstantiation对factory中所有bean生效。
  • 实际上,在实例化前阶段对bean的创建进行干预的情况,用的非常少,所以大部分bean的创建还会继续走下面的阶段。

4 bean实例化

这个过程中,我们不仅要了解bean的实例化过程,更关心spring为我们开发者提供的扩展点。

4.1 实例化过程

继续跟踪之前的代码AbstractAutowireCapableBeanFactory 的createBean()方法

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // 省略...
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean;
      }
   }
	// 省略...
   try {
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
     // 省略...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在我们对实例化前阶段对bean的创建不进行干预的情况下,继续执行doCreateBean()方法

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   // 省略
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

第一次创建bean,factoryBeanInstanceCache缓存中不会有instanceWrapper

  • BeanWrapper:对bean实例包装,在其实现类有属性存放bean实例对象。

继续执行createBeanInstance()方法

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   // 省略..
    // 自定义实现创建bean实例方法
   Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
   if (instanceSupplier != null) {
      return obtainFromSupplier(instanceSupplier, beanName);
   }
	// 通过工厂方法实例化bean
   if (mbd.getFactoryMethodName() != null) {
      return instantiateUsingFactoryMethod(beanName, mbd, args);
   }

   // Shortcut when re-creating the same bean...
	// 再次创建bean实例
    // 省略...

   // 扩展点,自定义确定bean构造器
   Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
   if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
      return autowireConstructor(beanName, mbd, ctors, args);
   }

   // BeanDefinition中定义的构造器
   ctors = mbd.getPreferredConstructors();
   if (ctors != null) {
      return autowireConstructor(beanName, mbd, ctors, null);
   }

   // 使用默认无参构造器实例化bean
   return instantiateBean(beanName, mbd);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • bean(初次)实例化5种方式,自上而下有优先级顺序,任何一种方式实例化bean返回
    • 自己在BeanDefinition定义中提供实例化bean方式,为Supplier接口
    • BeanDefinition定义中提供工厂方法,使用工厂方法实例化bean
    • 通过spring提供的扩展点即实现SmartInstantiationAwareBeanPostProcessor接口的determineCandidateConstructors()方法确定bean的构造器,通过该构造器实例化bean
    • BeanDefinition定义中提供构造器
    • 使用无参构造器实例化bean

除第一种方法外,其他都是通过反射创建bean的实例。这里我们主要讲解下通过扩展来实例化bean的方式。

4.2 SmartInstantiationAwareBeanPostProcessor扩展

看下determineConstructorsFromBeanPostProcessors()方法

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

   if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
      for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
         Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
         if (ctors != null) {
            return ctors;
         }
      }
   }
   return null;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

通过遍历BeanPostProcessor缓存的SmartInstantiationAwareBeanPostProcessor对象,执行determineCandidateConstructors()方法决定bean的构造器。

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
  • 1

可以将@Autowired标注的方法作为候选构造器返回,有兴趣的可以去看一下代码。

4.3 测试

bean Person

package com.gaogzhen.myspring.bean;

import com.gaogzhen.myspring.annotations.MyAutowired;

/**
 * @author: Administrator
 * @createTime: 2023/03/14 10:06
 */
public class Person {

    private String name;

    private Integer age;

    public Person() {
        System.out.println("默认构造器");
    }

    @MyAutowired
    public Person(String name) {
        System.out.println("@MyAutowired注解构造器");
        this.name = name;
    }

    public Person(String name, Integer age) {
        System.out.println("所有参数构造器");
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

自定义注解@MyAutowired

package com.gaogzhen.myspring.annotations;

import java.lang.annotation.*;

/**
 * @author: Administrator
 * @createTime: 2023/03/14 10:13
 */
@Target({ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAutowired {
    boolean required() default true;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

MySmartInstantiationAwareBeanPostProcessor实现SmartInstantiationAwareBeanPostProcessor接口

package com.gaogzhen.myspring.processors;

import com.gaogzhen.myspring.annotations.MyAutowired;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;

import java.lang.reflect.Constructor;
import java.util.Arrays;

/**
 * @author: Administrator
 * @createTime: 2023/03/14 10:12
 */
public class MySmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
    @Override
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
        if ("person".equalsIgnoreCase(beanClass.getSimpleName())) {
            System.out.println(beanClass);
            System.out.println("调用 MySmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors 方法");
            Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
            if (declaredConstructors != null) {
                //获取有@MyAutowired注解的构造器列表
                Constructor[] constructors = Arrays.stream(declaredConstructors).
                        filter(constructor -> constructor.isAnnotationPresent(MyAutowired.class))
                        .toArray(Constructor[]::new);
                return constructors.length != 0 ? constructors : null;
            }
        }
        return SmartInstantiationAwareBeanPostProcessor.super.determineCandidateConstructors(beanClass, beanName);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

测试方法

    @Test
    public void testSmartInstantiationAwareBeanPostProcessor() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

        factory.addBeanPostProcessor(new MySmartInstantiationAwareBeanPostProcessor());
        factory.registerBeanDefinition("name", BeanDefinitionBuilder.genericBeanDefinition(String.class)
                                                            .addConstructorArgValue("张三").getBeanDefinition());
        factory.registerBeanDefinition("age", BeanDefinitionBuilder.genericBeanDefinition(Integer.class)
                .addConstructorArgValue(25).getBeanDefinition());
        factory.registerBeanDefinition("person", BeanDefinitionBuilder.genericBeanDefinition(Person.class)
                .getBeanDefinition());
        Person person = factory.getBean("person", Person.class);
        System.out.println(person);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

输出结果:

class com.gaogzhen.myspring.bean.Person
调用 MySmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors 方法
2023-03-14 10:34:51 427 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'name'
2023-03-14 10:34:51 492 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'person' via constructor to bean named 'name'
@MyAutowired注解构造器
Person{name='张三', age=null}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 实例化时,使用了@MyAutowired注解的构造器

bean实例化暂时讲解到这里,继续bean生命周期后续旅程。

后记

如果小伙伴什么问题或者指教,欢迎交流。

❓QQ:806797785

⭐️源代码仓库地址:https://gitee.com/gaogzhen/spring6-study

参考:

[1]Spring系列之Bean生命周期详解[CP/OL]

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/66338
推荐阅读
相关标签
  

闽ICP备14008679号