全网最细致的spring源码分析(六):spring实例化策略

        上一章节,实例化过程中反复提到实例化策略,这到底是做什么的呢?事实上,在经过前面的分析,我们已经得到了足够用于实例化的所有信息,完全可以使用最简单的反射方式直接构建实例对象,但spring却不仅仅如此。

        spring初始化策略主要使用SimpleInstantiationStrategy类下的instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)方法。

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
   //bd中是否包含了MethodOverrides的列表,这里的Overrides并不是通常的意义上的多态,而是由spring提供的lookup-method,replaced-method标签生成的。
    //如果没有MethodOverrides直接就可以实例化
   if (!bd.hasMethodOverrides()) {
        //声明需要初始化的构造方法
      Constructor constructorToUse;
        //将这个db对象锁定,确保线程的安全
      synchronized (bd.constructorArgumentLock) {
            //从缓存中获取构造方法
         constructorToUse = (Constructor) bd.resolvedConstructorOrFactoryMethod;
            //没有获取到情况下,就进行生成
         if (constructorToUse == null) {
            //获取bean的类型
            final Class clazz = bd.getBeanClass();
            //如果是接口就无法实例化,抛出异常
            if (clazz.isInterface()) {
               throw new BeanInstantiationException(clazz, "Specified class is an interface");
            }
            try {
                //获取java的安全控制
               if (System.getSecurityManager() != null) {
                                //获取到对应的权限进行初始化
                  constructorToUse = AccessController.doPrivileged(
                        (PrivilegedExceptionAction>) clazz::getDeclaredConstructor);
               }
               else {
                    //获取构造方法
                  constructorToUse = clazz.getDeclaredConstructor();               }
                //bd中保留构造方法的缓存
               bd.resolvedConstructorOrFactoryMethod = constructorToUse;
            }
            catch (Throwable ex) {
               throw new BeanInstantiationException(clazz, "No default constructor found", ex);
            }
         }
      }
        //反射生成对象
      return BeanUtils.instantiateClass(constructorToUse);
   }
   else {
      // 如果有MethodOverrides对象,需要使用cglib来进行代理
      return instantiateWithMethodInjection(bd, beanName, owner);
   }
}

instantiateWithMethodInjection(bd, beanName, owner)通过一串委托之后,最终会调用到CglibSubclassingInstantiationStrategy类下的instantiate(@Nullable Constructor ctor, Object... args)方法来完成代理对象的生成

public Object instantiate(@Nullable Constructor ctor, Object... args) {
    //cglib是通过创建被代理对象的子类,并重写方法完成代理过程。这里就是生成被代理对象的子类
   Class subclass = createEnhancedSubclass(this.beanDefinition);
   Object instance;
   if (ctor == null) {
        //如果没有构造方法,直接使用代理对象的构造方法实例化对象
      instance = BeanUtils.instantiateClass(subclass);
   }
   else {
      try {
            //根据被代理对象的构造方法参数,找到代理对象的对应构造方法
         Constructor enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
            //通过构造方法实例化代理对象
         instance = enhancedSubclassConstructor.newInstance(args);
      }
      catch (Exception ex) {
         throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
              "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
      }
   }
   // SPR-10785: set callbacks directly on the instance instead of in the
   // enhanced class (via the Enhancer) in order to avoid memory leaks.
    //对实例化对象进行方法增强(详细使用查看cglib的使用)
   Factory factory = (Factory) instance;
   factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
         new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
         new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
   return instance;
}

        spring在做实例化策略的时候,首先判断了beanDefinition中是否有MethodOverrides,也就是用户有没有配置replace或者lookup的配置方法,如果没有配置就是直接使用反射的方式,简单粗暴的生成bean,但如果用户配置了这两方法,就不能这么简单的解决了,因为需要将这两个配置提供的功能切入进去,spring通过cglib的动态代理的方式将包含这两个特性对应的逻辑的拦截增强器设置进去,这样被代理对象的方法通过代理对象增强了。

你可能感兴趣的:(Spring)