美文网首页
spring容器之bean的初始化策略(Instantiatio

spring容器之bean的初始化策略(Instantiatio

作者: 会上树的程序猿 | 来源:发表于2019-08-11 22:22 被阅读0次

在看InstantiationStrategy之前我们先来简单的回顾下我们bean的实例化过程:

  • 我们在AbstractAutowireCapableBeanFactory#doCreateBean(...)方法中完成了bean的创建过程,期间在该方法中有bean的初始化 属性的设置以及bean的实例化入口,其中在bean的实例化过程中是根据bean的类型进行判断,如果当前bean是单例,从factoryBeanInstanceCach中获取,反之通过#createBeanInstance(...)来创建.
  • 如果是通过#createBeanInstance(...)方法进行bean实例的创建:
    - 通过Supplier来判断,该Supplier不为null,则通过方法#obtainFromSupplier(...)进行bean的实例化操作.
    - 如果factory不为null,则调用 #instantiateUsingFactoryMethod(...) 方法来实例化Bean.
    - 如果都不是上面的两者,则调用默认的方法#instantiateBean(...)来完成bean的实例化操作.

不过上述是如何操作的过程,其最终都会经过InstantiationStrategy的instantiate(....)方法,接下来我们看一下该InstantiationStrategy接口:

InstantiationStrategy
public interface InstantiationStrategy {

/**
 * 默认的构造方法
 * @param bd
 * @param beanName
 * @param owner
 * @return
 * @throws BeansException
 */
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)throws BeansException;
/**
 * 指定构造方法
 * @param bd
 * @param beanName
 * @param owner
 * @param ctor
 * @param args
 * @return
 * @throws BeansException
 */

Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
        Constructor<?> ctor, Object... args) throws BeansException;
/**
 * 通过指定的工厂方法
 * @param bd
 * @param beanName
 * @param owner
 * @param factoryBean
 * @param factoryMethod
 * @param args
 * @return
 * @throws BeansException
 */
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
        @Nullable Object factoryBean, Method factoryMethod, Object... args)
        throws BeansException;

可以看到的是InstantiationStrategy接口为Bean的初始化提供了三种策略化方法,根据bean的不同选择不同的策略模式进行实例化过程,我们分别来看:

1.默认的构造方法
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // Don't override the class with CGLIB if no overrides.
    //如果没有方法被覆盖,通过BeanUtils#instantiateClass来初始化(实质是利用反射来创建)
    if (!bd.hasMethodOverrides()) {
        Constructor<?> constructorToUse;
        //加锁
        synchronized (bd.constructorArgumentLock) {
            //获取构造方法constructorToUse
            constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
            if (constructorToUse == null) {
                //获取Bean的class的对象
                final Class<?> clazz = bd.getBeanClass();
                //如果clazz是接口类型的,直接抛BeanInstantiationException异常
                if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
                }
                try {
                    //在当前系统安全模式的情况下
                    if (System.getSecurityManager() != null) {
                        constructorToUse = AccessController.doPrivileged(
                                (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
                    }
                    //获取构造方法
                    else {
                        constructorToUse = clazz.getDeclaredConstructor();
                    }
                    //将constructorToUse赋给resolvedConstructorOrFactoryMethod属性
                    bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                }
                catch (Throwable ex) {
                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                }
            }
        }
        //通过BeanUtils直接使用构造器对象实例化Bean对象
        return BeanUtils.instantiateClass(constructorToUse);
    }
    else {
        // Must generate CGLIB subclass.
        //生成CGLIB创建的子类对象
        return instantiateWithMethodInjection(bd, beanName, owner);
    }
}

在构造方法策略模式中,首先是判断是否有方法被覆盖,如果没有则直接通过反射的方式来创建,如果有的话则通过CGLIB来实例化对象.

2.指定的构造方法
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
        final Constructor<?> ctor, Object... args) {
    //判断是否有方法需要重载
    if (!bd.hasMethodOverrides()) {
        if (System.getSecurityManager() != null) {
            // use own privileged to change accessibility (when security is on)
            //设置访问权限
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                ReflectionUtils.makeAccessible(ctor);
                return null;
            });
        }
        //通过 BeanUtils直接使用构造器对象实例化Bean对象
        return BeanUtils.instantiateClass(ctor, args);
    }
    else {
        //2初始化CGLB对象
        return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
    }
}

通过指定的构造方法我们可以发现跟默认的构造方法类似

3.工厂方法
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
        @Nullable Object factoryBean, final Method factoryMethod, Object... args) {

    try {
        //设置方法的访问权限
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                ReflectionUtils.makeAccessible(factoryMethod);
                return null;
            });
        }
        else {
            ReflectionUtils.makeAccessible(factoryMethod);
        }
        //获取之前的方法
        Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
        try {
            //将新的工厂方法保存到currentlyInvokedFactoryMethod中
            currentlyInvokedFactoryMethod.set(factoryMethod);
            //创建bean对象
            Object result = factoryMethod.invoke(factoryBean, args);
            //没创建成功,则创建一个nullBean来代替
            if (result == null) {
                result = new NullBean();
            }
            //创建成功的话,直接返回
            return result;
        }
        finally {
            if (priorInvokedFactoryMethod != null) {
                //覆盖之前的方法
                currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
            }
            else {
                currentlyInvokedFactoryMethod.remove();
            }
        }
    }
    //后面都是些异常处理
    catch (IllegalArgumentException ex) {
        throw new BeanInstantiationException(factoryMethod,
                "Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
                "args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
    }
    catch (IllegalAccessException ex) {
        throw new BeanInstantiationException(factoryMethod,
                "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
    }
    catch (InvocationTargetException ex) {
        String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
        if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
                ((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
            msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
                    "declaring the factory method as static for independence from its containing instance. " + msg;
        }
        throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
    }
}

工厂方法的处理更简单直接,不用考虑,直接利用反射的方式来初始化对象

CglibSubclassingInstantiationStrategy

关于CglibSubclassingInstantiationStrategy,该类继承于SimpleInstantiationStrategy与此同时该类也是spring默认的实例化bean的策略,也是CGLIB实例化bean的委托对象的实现类.

在我们的SimpleInstantiationStrategy类中有这样一段代码:

protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");
}

同样的在CglibSubclassingInstantiationStrategy子类中:

@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    return instantiateWithMethodInjection(bd, beanName, owner, null);
}

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

    // Must generate CGLIB subclass...
    //生成一个CGLB子类对象
    return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
}

我们可以发现,显然子类CglibSubclassingInstantiationStrategy中对该方法进行了增强处理.其实例化bean的时候实际上是由CglibSubclassCreator来实现:

    public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
        //创建一个cglb的代理类
        Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
        Object instance;
        //<2>如果当前构造器不存在,通过BeanUtils调用默认构造器来创建
        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.
        //避免内存泄露,直接在bean实例上设置回调
        Factory factory = (Factory) instance;
        factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
                new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
                new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
        return instance;
    }

我们可以发现,一进入方法通过调用#createEnhancedSubclass(...)来提供BeanDefinition创建bean的增强子类,代码如下:

/**
     * Create an enhanced subclass of the bean class for the provided bean
     * definition, using CGLIB.
     */
    private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
        //创建Enhancer对象
        Enhancer enhancer = new Enhancer();
        //设置当前bean的class类型
        enhancer.setSuperclass(beanDefinition.getBeanClass());
        //设置spring的命名策略
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        //设置生成策略
        if (this.owner instanceof ConfigurableBeanFactory) {
            ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
            enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
        }
        // 过滤,自定义逻辑来指定调用的callback下标
        enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
        enhancer.setCallbackTypes(CALLBACK_TYPES);
        return enhancer.createClass();
    }

在<2>处,如果ctor为null时,则通过BeanUtils#instantiateClass(subclass)来实例化bean,否则则根据构造函数类型获取具体的构造器,调用Constructor#newInstance(args) 方法来实例化.

MethodOverrideCallbackFilter

在我们的#createEnhancedSubclass(...)方法中的末尾,我们通过过滤,自定义逻辑来指定调用的callback下标,也就是以下代码:

enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
enhancer.setCallbackTypes(CALLBACK_TYPES);

我们发现在设置CallbackFilter属性时首先是创建一个MethodOverrideCallbackFilter对象,我们来看看它到底是什么?

  • 原来发现MethodOverrideCallbackFilter继承于CglibIdentitySupport同时实现了CallbackFilter接口.
  • 其次CallbackFilter是一个CGLIB 的一个回调过滤器接口.
  • CglibIdentitySupport 则为 CGLIB 提供 #hashCode() 和 #equals(Object o) 方法,以确保 CGLIB 不会为每个 Bean 生成不同的类.
  • MethodOverrideCallbackFilter 实现 CallbackFilter 的 #accept(Method method) 方法:
public int accept(Method method) {
        MethodOverride methodOverride = getBeanDefinition().getMethodOverrides().getOverride(method);
        if (logger.isTraceEnabled()) {
            logger.trace("Override for '" + method.getName() + "' is [" + methodOverride + "]");
        }
        if (methodOverride == null) {
            return PASSTHROUGH;
        }
        else if (methodOverride instanceof LookupOverride) {
            return LOOKUP_OVERRIDE;
        }
        else if (methodOverride instanceof ReplaceOverride) {
            return METHOD_REPLACER;
        }
        throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " +
                methodOverride.getClass().getName());
    }

在accept方法中,通过其methodOverride返回的值来判断,其中上述代码中的PASSTHROUGH 和 LOOKUP_OVERRIDE以及METHOD_REPLACER为Callback数组的下标,这里的数组为CALLBACK_TYPES数组,代码如下:

private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
            {NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};

在上述的数组中我们看到定义了两个拦截器,接下来我们分别来看:

LookupOverrideMethodInterceptor
/**
 * CGLIB MethodInterceptor to override methods, replacing them with an
 * implementation that returns a bean looked up in the container.
 */
private static class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {

    private final BeanFactory owner;

    public LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
        super(beanDefinition);
        this.owner = owner;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
        // Cast is safe, as CallbackFilter filters are used selectively.
        //通过method来获取LookupOverride对象
        LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
        Assert.state(lo != null, "LookupOverride not found");
        //获取参数
        Object[] argsToUse = (args.length > 0 ? args : null);  // if no-arg, don't insist on args at all
        //获取bean
        if (StringUtils.hasText(lo.getBeanName())) {
            //如果参数argsToUse不为null,通过name去获取
            return (argsToUse != null ? this.owner.getBean(lo.getBeanName(), argsToUse) :
                    this.owner.getBean(lo.getBeanName()));
        }
        else {
            //通过type去获取
            return (argsToUse != null ? this.owner.getBean(method.getReturnType(), argsToUse) :
                    this.owner.getBean(method.getReturnType()));
        }
    }
}
ReplaceOverrideMethodInterceptor
/**
 * CGLIB MethodInterceptor to override methods, replacing them with a call
 * to a generic MethodReplacer.
 */
private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {

    private final BeanFactory owner;

    public ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
        super(beanDefinition);
        this.owner = owner;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
        //通过method来获取ReplaceOverride对象
        ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
        Assert.state(ro != null, "ReplaceOverride not found");
        // TODO could cache if a singleton for minor performance optimization
        //获取MethodReplacer对象
        MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
        //进行替换操作
        return mr.reimplement(obj, method, args);
    }
}

到这里,关于初始化的策略模式知识我们讲到这里了...

相关文章

网友评论

      本文标题:spring容器之bean的初始化策略(Instantiatio

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