【Spring】——IoC 之 Bean 的实例化策略:InstantiationStrategy

2020-12-05 · 芋道源码 · 转载 · · 本文共 1,378个字,预计阅读需要 5分钟。

转载于【芋道源码

本文主要基于 Spring 5.0.6.RELEASE

在开始分析 InstantiationStrategy 之前,我们先来简单回顾下 Bean 的实例化过程:

  1. Bean 的创建,主要是 AbstractAutowireCapableBeanFactory#doCreateBean(...) 方法。在这个方法中有 Bean 的实例化、属性注入和初始化过程,对于 Bean 的实例化过程这是根据 Bean 的类型来判断的,如果是单例模式,则直接从 factoryBeanInstanceCache 缓存中获取,否则调用 #createBeanInstance(...) 方法来创建。
  2. #createBeanInstance(...) 方法中,如果 Supplier 不为空,则调用 #obtainFromSupplier(...) 实例化 bean。如果 factory 不为空,则调用 #instantiateUsingFactoryMethod(...) 方法来实例化 Bean 。如果都不是,则调用 #instantiateBean(...) 方法来实例化 Bean 。但是无论是 #instantiateUsingFactoryMethod(...) 方法,还是 #instantiateBean() 方法,最后都一定会调用到 InstantiationStrategy 接口的 #instantiate(...) 方法。

1. InstantiationStrategy

InstantiationStrategy 接口定义了 Spring Bean 实例化的策略,根据创建对象情况的不同,提供了三种策略:无参构造方法、有参构造方法、工厂方法。代码如下:

  1. public interface InstantiationStrategy {
  2. /**
  3. * 默认构造方法
  4. */
  5. Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)
  6. throws BeansException;
  7. /**
  8. * 指定构造方法
  9. */
  10. Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
  11. Constructor<?> ctor, @Nullable Object... args) throws BeansException;
  12. /**
  13. * 工厂方法
  14. */
  15. Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
  16. @Nullable Object factoryBean, Method factoryMethod, @Nullable Object... args)
  17. throws BeansException;
  18. }

2. SimpleInstantiationStrategy

InstantiationStrategy 接口有两个实现类:SimpleInstantiationStrategy 和 CglibSubclassingInstantiationStrategy。

SimpleInstantiationStrategy 对以上三个方法都做了简单的实现。

① 如果是工厂方法实例化,则直接使用反射创建对象,如下:

  1. // SimpleInstantiationStrategy.java
  2. @Override
  3. public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
  4. @Nullable Object factoryBean, final Method factoryMethod, Object... args) {
  5. try {
  6. // 设置 Method 可访问
  7. if (System.getSecurityManager() != null) {
  8. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  9. ReflectionUtils.makeAccessible(factoryMethod);
  10. return null;
  11. });
  12. } else {
  13. ReflectionUtils.makeAccessible(factoryMethod);
  14. }
  15. // 获得原 Method 对象
  16. Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
  17. try {
  18. // 设置新的 Method 对象,到 currentlyInvokedFactoryMethod 中
  19. currentlyInvokedFactoryMethod.set(factoryMethod);
  20. // 创建 Bean 对象
  21. Object result = factoryMethod.invoke(factoryBean, args);
  22. // 未创建,则创建 NullBean 对象
  23. if (result == null) {
  24. result = new NullBean();
  25. }
  26. return result;
  27. } finally {
  28. // 设置老的 Method 对象,到 currentlyInvokedFactoryMethod 中
  29. if (priorInvokedFactoryMethod != null) {
  30. currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
  31. } else {
  32. currentlyInvokedFactoryMethod.remove();
  33. }
  34. }
  35. // 一大堆 catch 异常
  36. } catch (IllegalArgumentException ex) {
  37. throw new BeanInstantiationException(factoryMethod,
  38. "Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
  39. "args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
  40. } catch (IllegalAccessException ex) {
  41. throw new BeanInstantiationException(factoryMethod,
  42. "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
  43. } catch (InvocationTargetException ex) {
  44. String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
  45. if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
  46. ((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
  47. msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
  48. "declaring the factory method as static for independence from its containing instance. " + msg;
  49. }
  50. throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
  51. }
  52. }

② 如果是构造方法实例化,则是先判断是否有 MethodOverrides,如果没有则是直接使用反射,如果有则就需要 CGLIB 实例化对象。如下:

  1. // SimpleInstantiationStrategy.java
  2. // 默认构造方法
  3. @Override
  4. public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
  5. // Don't override the class with CGLIB if no overrides.
  6. // 没有覆盖,直接使用反射实例化即可
  7. if (!bd.hasMethodOverrides()) {
  8. Constructor<?> constructorToUse;
  9. synchronized (bd.constructorArgumentLock) {
  10. // 获得构造方法 constructorToUse
  11. constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
  12. if (constructorToUse == null) {
  13. final Class<?> clazz = bd.getBeanClass();
  14. // 如果是接口,抛出 BeanInstantiationException 异常
  15. if (clazz.isInterface()) {
  16. throw new BeanInstantiationException(clazz, "Specified class is an interface");
  17. }
  18. try {
  19. // 从 clazz 中,获得构造方法
  20. if (System.getSecurityManager() != null) { // 安全模式
  21. constructorToUse = AccessController.doPrivileged(
  22. (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
  23. } else {
  24. constructorToUse = clazz.getDeclaredConstructor();
  25. }
  26. // 标记 resolvedConstructorOrFactoryMethod 属性
  27. bd.resolvedConstructorOrFactoryMethod = constructorToUse;
  28. } catch (Throwable ex) {
  29. throw new BeanInstantiationException(clazz, "No default constructor found", ex);
  30. }
  31. }
  32. }
  33. // 通过 BeanUtils 直接使用构造器对象实例化 Bean 对象
  34. return BeanUtils.instantiateClass(constructorToUse);
  35. } else {
  36. // Must generate CGLIB subclass.
  37. // 生成 CGLIB 创建的子类对象
  38. return instantiateWithMethodInjection(bd, beanName, owner);
  39. }
  40. }
  41. // 指定构造方法
  42. @Override
  43. public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
  44. final Constructor<?> ctor, Object... args) {
  45. // 没有覆盖,直接使用反射实例化即可
  46. if (!bd.hasMethodOverrides()) {
  47. if (System.getSecurityManager() != null) {
  48. // 设置构造方法,可访问
  49. // use own privileged to change accessibility (when security is on)
  50. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  51. ReflectionUtils.makeAccessible(ctor);
  52. return null;
  53. });
  54. }
  55. // 通过 BeanUtils 直接使用构造器对象实例化 Bean 对象
  56. return BeanUtils.instantiateClass(ctor, args);
  57. } else {
  58. // 生成 CGLIB 创建的子类对象
  59. return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
  60. }
  61. }
  • SimpleInstantiationStrategy 对 #instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner, Constructor<?> ctor, Object... args) 的实现任务交给了子类 CglibSubclassingInstantiationStrategy 。

3. MethodOverrides

对于 MethodOverrides,如果读者是跟着小编文章一路跟过来的话一定不会陌生,在 BeanDefinitionParserDelegate 类解析 <bean/> 的时候是否还记得这两个方法:#parseLookupOverrideSubElements(...)#parseReplacedMethodSubElements(...) 这两个方法分别用于解析 lookup-methodreplaced-method 属性。

其中,#parseLookupOverrideSubElements(...) 源码如下:

parseLookupOverrideSubElements

更多关于 lookup-methodreplaced-method 请看:【死磕 Spring】—– IoC 之解析 bean 标签:meta、lookup-method、replace-method

4. CglibSubclassingInstantiationStrategy

类 CglibSubclassingInstantiationStrategy 为 Spring 实例化 Bean 的默认实例化策略,其主要功能还是对父类功能进行补充:其父类将 CGLIB 的实例化策略委托其实现。

  1. // SimpleInstantiationStrategy.java
  2. protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
  3. throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");
  4. }
  5. // CglibSubclassingInstantiationStrategy.java
  6. @Override
  7. protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
  8. return instantiateWithMethodInjection(bd, beanName, owner, null);
  9. }
  • CglibSubclassingInstantiationStrategy 实例化 Bean 策略,是通过其内部类 CglibSubclassCreator 来实现的。代码如下:

    1. // CglibSubclassingInstantiationStrategy.java
    2. @Override
    3. protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Constructor<?> ctor, Object... args) {
    4. // Must generate CGLIB subclass...
    5. // 通过CGLIB生成一个子类对象
    6. return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
    7. }
  • 创建 CglibSubclassCreator 实例,然后调用其 #instantiate(Constructor<?> ctor, Object... args) 方法,该方法用于动态创建子类实例,同时实现所需要的 lookups(lookup-methodreplace-method)。

    1. // CglibSubclassingInstantiationStrategy.java#CglibSubclassCreator
    2. public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
    3. // <x> 通过 Cglib 创建一个代理类
    4. Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
    5. Object instance;
    6. // <y> 没有构造器,通过 BeanUtils 使用默认构造器创建一个bean实例
    7. if (ctor == null) {
    8. instance = BeanUtils.instantiateClass(subclass);
    9. } else {
    10. try {
    11. // 获取代理类对应的构造器对象,并实例化 bean
    12. Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
    13. instance = enhancedSubclassConstructor.newInstance(args);
    14. } catch (Exception ex) {
    15. throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
    16. "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
    17. }
    18. }
    19. // SPR-10785: set callbacks directly on the instance instead of in the
    20. // enhanced class (via the Enhancer) in order to avoid memory leaks.
    21. // 为了避免 memory leaks 异常,直接在 bean 实例上设置回调对象
    22. Factory factory = (Factory) instance;
    23. factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
    24. new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
    25. new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
    26. return instance;
    27. }
    • <x> 处,调用 #createEnhancedSubclass(RootBeanDefinition beanDefinition) 方法,为提供的 BeanDefinition 创建 bean 类的增强子类。代码如下:

      1. // CglibSubclassingInstantiationStrategy.java#CglibSubclassCreator
      2. private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
      3. // 创建 Enhancer 对象
      4. Enhancer enhancer = new Enhancer();
      5. // 设置 Bean 类
      6. enhancer.setSuperclass(beanDefinition.getBeanClass());
      7. // 设置 Spring 的命名策略
      8. enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
      9. // 设置生成策略
      10. if (this.owner instanceof ConfigurableBeanFactory) {
      11. ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
      12. enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
      13. }
      14. // 过滤,自定义逻辑来指定调用的callback下标
      15. enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
      16. enhancer.setCallbackTypes(CALLBACK_TYPES);
      17. return enhancer.createClass();
      18. }
      • CGLIB 的标准 API 的使用。
    • <y> 处,获取子类增强 subclass 后,如果 Constructor 实例 ctr 为空,则调用默认构造函数(BeanUtils#instantiateClass(subclass))来实例化类,否则则根据构造函数类型获取具体的构造器,调用 Constructor#newInstance(args) 方法来实例化类。

4.1 MethodOverrideCallbackFilter

<x> 处调用的 #createEnhancedSubclass(RootBeanDefinition beanDefinition) 方法,我们注意两行代码:

  1. // CglibSubclassingInstantiationStrategy.java#CglibSubclassCreator
  2. enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
  3. enhancer.setCallbackTypes(CALLBACK_TYPES);
  • 通过 MethodOverrideCallbackFilter 来定义调用 callback 类型。

MethodOverrideCallbackFilter 是用来定义 CGLIB 回调过滤方法的拦截器行为,它继承 CglibIdentitySupport 实现 CallbackFilter 接口。

  • CallbackFilter 是 CGLIB 的一个回调过滤器。
  • CglibIdentitySupport 则为 CGLIB 提供 #hashCode()#equals(Object o) 方法,以确保 CGLIB 不会为每个 Bean 生成不同的类。

MethodOverrideCallbackFilter 实现 CallbackFilter 的 #accept(Method method) 方法,代码如下:

  1. // CglibSubclassingInstantiationStrategy.java#MethodOverrideCallbackFilter
  2. @Override
  3. public int accept(Method method) {
  4. MethodOverride methodOverride = getBeanDefinition().getMethodOverrides().getOverride(method);
  5. if (logger.isTraceEnabled()) {
  6. logger.trace("Override for '" + method.getName() + "' is [" + methodOverride + "]");
  7. }
  8. if (methodOverride == null) {
  9. return PASSTHROUGH;
  10. } else if (methodOverride instanceof LookupOverride) {
  11. return LOOKUP_OVERRIDE;
  12. } else if (methodOverride instanceof ReplaceOverride) {
  13. return METHOD_REPLACER;
  14. }
  15. throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " +
  16. methodOverride.getClass().getName());
  17. }
  • 根据 BeanDefinition 中定义的 MethodOverride 不同,返回不同的值, 这里返回的 PASSTHROUGHLOOKUP_OVERRIDEMETHOD_REPLACER 都是 Callback 数组的下标,这里对应的数组为 CALLBACK_TYPES 数组,如下:

    1. // CglibSubclassingInstantiationStrategy.java#CglibSubclassCreator
    2. private static final Class<?>[] CALLBACK_TYPES = new Class<?>[] {
    3. NoOp.class,
    4. LookupOverrideMethodInterceptor.class,
    5. ReplaceOverrideMethodInterceptor.class
    6. };

4.2 LookupOverrideMethodInterceptor

  1. // CglibSubclassingInstantiationStrategy.java#LookupOverrideMethodInterceptor
  2. private static class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
  3. private final BeanFactory owner;
  4. public LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
  5. super(beanDefinition);
  6. this.owner = owner;
  7. }
  8. @Override
  9. public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
  10. // Cast is safe, as CallbackFilter filters are used selectively.
  11. // 获得 method 对应的 LookupOverride 对象
  12. LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
  13. Assert.state(lo != null, "LookupOverride not found");
  14. // 获得参数
  15. Object[] argsToUse = (args.length > 0 ? args : null); // if no-arg, don't insist on args at all
  16. // 获得 Bean
  17. if (StringUtils.hasText(lo.getBeanName())) { // Bean 的名字
  18. return (argsToUse != null ? this.owner.getBean(lo.getBeanName(), argsToUse) :
  19. this.owner.getBean(lo.getBeanName()));
  20. } else { // Bean 的类型
  21. return (argsToUse != null ? this.owner.getBean(method.getReturnType(), argsToUse) :
  22. this.owner.getBean(method.getReturnType()));
  23. }
  24. }
  25. }

4.3 ReplaceOverrideMethodInterceptor

  1. // CglibSubclassingInstantiationStrategy.java#ReplaceOverrideMethodInterceptor
  2. private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
  3. private final BeanFactory owner;
  4. public ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
  5. super(beanDefinition);
  6. this.owner = owner;
  7. }
  8. @Override
  9. public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
  10. // 获得 method 对应的 LookupOverride 对象
  11. ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
  12. Assert.state(ro != null, "ReplaceOverride not found");
  13. // TODO could cache if a singleton for minor performance optimization
  14. // 获得 MethodReplacer 对象
  15. MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
  16. // 执行替换
  17. return mr.reimplement(obj, method, args);
  18. }
  19. }