Spring IOC 的实例化策略 && BeanDefinitionRegistry

241 阅读5分钟

1 简介

InstantiationStrategy 定义了Spring的实例化策略,共有3个策略

  • 无参构造方法
  • 工厂方法
  • 有参构造方法 InstantiationStrategy 接口有两个实现类:SimpleInstantiationStrategyCglibSubclassingInstantiationStrategy。其中SimpleInstantiationStrategy 对以上三个方法都做了简单的实现

源码奉上

public interface InstantiationStrategy {

    /**
    * 默认构造方法
    */
    Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)
    throws BeansException;

    /**
    * 有参构造方法
    */
    Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
    Constructor<?> ctor, @Nullable Object... args) throws BeansException;

    /**
    * 工厂方法
    */
    Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
    @Nullable Object factoryBean, Method factoryMethod, @Nullable Object... args)
    throws BeansException;

}

2 子接口SimpleInstantiationStrategy

2.1 工厂方法

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
        @Nullable Object factoryBean, final Method factoryMethod, Object... args) {
    try {
        // 设置 Method 为可访问,主要是类修饰符,方法修饰符等
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                ReflectionUtils.makeAccessible(factoryMethod);
                return null;
            });
        } else {
            ReflectionUtils.makeAccessible(factoryMethod);
        }

        // 获得原 Method 对象,主要是为了后面再回复原值
        Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
        try {
            // 设置新的 Method 对象,到 currentlyInvokedFactoryMethod 中
            currentlyInvokedFactoryMethod.set(factoryMethod);
            // 创建 Bean 对象
            Object result = factoryMethod.invoke(factoryBean, args);
            // 未创建,则创建 NullBean 对象
            if (result == null) {
                result = new NullBean();
            }
            return result;
        } finally {
            // 设置老的 Method 对象,到 currentlyInvokedFactoryMethod 中
            if (priorInvokedFactoryMethod != null) {
                currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
            } else {
                currentlyInvokedFactoryMethod.remove();
            }
        }
    // 一大堆 catch 异常
    } catch (IllegalArgumentException ex) {
        //一大堆异常代码省略
    }
}

2.2 带参构造方法

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
		final Constructor<?> ctor, Object... args) {
        // 没有覆盖,直接使用反射实例化即可
	if (!bd.hasMethodOverrides()) {
		if (System.getSecurityManager() != null) {
                    // 设置构造方法,可访问
                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        ReflectionUtils.makeAccessible(ctor);
                        return null;
                    });
		}
        // 通过 BeanUtils 直接使用构造器对象实例化 Bean 对象
		return BeanUtils.instantiateClass(ctor, args);
	} else {
            // 生成 CGLIB 创建的子类对象
            return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
	}
}

2.4 无参构造

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // 没有覆盖,直接使用反射实例化即可
    if (!bd.hasMethodOverrides()) {
        Constructor<?> constructorToUse;
        synchronized (bd.constructorArgumentLock) {
        // 获得构造方法 constructorToUse
        constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
        if (constructorToUse == null) {
            final Class<?> clazz = bd.getBeanClass();
            // 如果是接口,抛出 BeanInstantiationException 异常
            if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
            }
            try {
                // 从 clazz 中,获得构造方法
                    if (System.getSecurityManager() != null) { // 安全模式
                            constructorToUse = AccessController.doPrivileged(
                                            (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
                    } else {
                            constructorToUse =	clazz.getDeclaredConstructor();
                    }
                    // 标记 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);
    }
}

3CglibSubclassingInstantiationStrategy

CglibSubclassingInstantiationStrategySimpleInstantiationStrategy的子接口,主要实现了instantiateWithMethodInjection 方法,源码如下

CglibSubclassingInstantiationStrategy 的实例化策略是通过其子类CglibSubclassCreator 实现的,最终是调用CglibSubclassCreator.instantiate 方法

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

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

    //  通过 CGLIB 派生一个子类
    return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
}


/**
 * An inner class created for historical reasons to avoid external CGLIB dependency
 * in Spring versions earlier than 3.2.
 */
private static class CglibSubclassCreator {

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

        private final RootBeanDefinition beanDefinition;

        private final BeanFactory owner;

        CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
                this.beanDefinition = beanDefinition;
                this.owner = owner;
        }

        
        public Object instantiate(Constructor<?> ctor, Object... args) {
            // <x> 通过 Cglib 创建一个代理类
            Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
            Object instance;
            //没有构造器,通过 BeanUtils 使用默认构造器创建一个bean实例
            if (ctor == null) {
                instance = BeanUtils.instantiateClass(subclass);
            }
            else {
                try {
                    //获取代理类对应的构造器对象,并实例化 bean
                    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);
                }
            }
            //直接在 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;
        }

        
        private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
            // 创建 Enhancer 对象
            Enhancer enhancer = new Enhancer();
            // 设置 Bean 类
            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));
            }
            enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
            enhancer.setCallbackTypes(CALLBACK_TYPES);
            return enhancer.createClass();
    }
}

4 注册表BeanDefinitionRegistry

BeanDefinitionRegistry 将bean的资源文件解析成BeanDefinition,并且注入到容器中

image.png

4.1 别名管理通用接口AliasRegistry

public interface AliasRegistry {

    void registerAlias(String name, String alias);
    void removeAlias(String alias);

    boolean isAlias(String name);
    String[] getAliases(String name);

}

4.2 BeanDefinitionRegistry

BeanDefinitionRegistry 是 Spring 的 Bean 工厂包中唯一封装 BeanDefinition 注册的接口。该接口定义了关于 BeanDefinition 注册、注销、查询等一系列的操作。

public interface BeanDefinitionRegistry extends AliasRegistry {

    // 往注册表中注册一个新的 BeanDefinition 实例
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;

    // 移除注册表中已注册的 BeanDefinition 实例
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    // 从注册中取得指定的 BeanDefinition 实例
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    // 判断 BeanDefinition 实例是否在注册表中(是否注册)
    boolean containsBeanDefinition(String beanName);

    // 取得注册表中所有 BeanDefinition 实例的 beanName(标识)
    String[] getBeanDefinitionNames();

    // 返回注册表中 BeanDefinition 实例的数量
    int getBeanDefinitionCount();

    // beanName(标识)是否被占用
    boolean isBeanNameInUse(String beanName);

}

4.3 实现接口

4.3.1 SimpleBeanDefinitionRegistry

SimpleBeanDefinitionRegistryBeanDefinitionRegistry 一个简单的实现,仅仅提供注册功能,无工厂功能,SimpleBeanDefinitionRegistry 使用 ConcurrentHashMap 来存储注册的 BeanDefinition

public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {

    /** Map of bean definition objects, keyed by bean name */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);


    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
                    throws BeanDefinitionStoreException {

            Assert.hasText(beanName, "'beanName' must not be empty");
            Assert.notNull(beanDefinition, "BeanDefinition must not be null");
            this.beanDefinitionMap.put(beanName, beanDefinition);
    }

    @Override
    public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
            if (this.beanDefinitionMap.remove(beanName) == null) {
                    throw new NoSuchBeanDefinitionException(beanName);
            }
    }

    @Override
    public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
            BeanDefinition bd = this.beanDefinitionMap.get(beanName);
            if (bd == null) {
                    throw new NoSuchBeanDefinitionException(beanName);
            }
            return bd;
    }

    @Override
    public boolean containsBeanDefinition(String beanName) {
            return this.beanDefinitionMap.containsKey(beanName);
    }

    @Override
    public String[] getBeanDefinitionNames() {
            return StringUtils.toStringArray(this.beanDefinitionMap.keySet());
    }

    @Override
    public int getBeanDefinitionCount() {
            return this.beanDefinitionMap.size();
    }

    @Override
    public boolean isBeanNameInUse(String beanName) {
            return isAlias(beanName) || containsBeanDefinition(beanName);
    }

}

4.3.2DefaultListableBeanFactory

DefaultListableBeanFactory 同时实现了ConfigurableListableBeanFactoryBeanDefinitionRegistry 是一个基于 BeanDefinition 元数据的完整 bean 工厂。DefaultListableBeanFactory 是一个具有注册功能的完整 Bean 工厂。它同样是用 ConcurrentHashMap 数据结构来存储注册的 BeanDefinition

// 注册表,由 BeanDefinition 的标识 (beanName) 与其实例组成
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, bean>(64);

// 标识(beanName)集合
private final List<String> beanDefinitionNames = new ArrayList<String>(64);


public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
   throws BeanDefinitionStoreException {

    // ... 省略其他代码

    // 如果未存在
    } else {
        // 检测创建 Bean 阶段是否已经开启,如果开启了则需要对 beanDefinitionMap 进行并发控制
        if (hasBeanCreationStarted()) {
            // beanDefinitionMap 为全局变量,避免并发情况
            
            synchronized (this.beanDefinitionMap) {
                //  添加到 BeanDefinition 到 beanDefinitionMap 中。
                this.beanDefinitionMap.put(beanName, beanDefinition);
                // 添加 beanName 到 beanDefinitionNames 中
                List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                // 从 manualSingletonNames 移除 beanName
                if (this.manualSingletonNames.contains(beanName)) {
                    Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
                    updatedSingletons.remove(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        } else {
            // Still in startup registration phase
            // 添加到 BeanDefinition 到 beanDefinitionMap 中。
            this.beanDefinitionMap.put(beanName, beanDefinition);
            // 添加 beanName 到 beanDefinitionNames 中
            this.beanDefinitionNames.add(beanName);
            // 从 manualSingletonNames 移除 beanName
            this.manualSingletonNames.remove(beanName);
        }

        this.frozenBeanDefinitionNames = null;
    }

    // 重新设置 beanName 对应的缓存
    if (existingDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }

}
  • 注册的核心代码时this.beanDefinitionMap.put(beanName, beanDefinition);
  • 销毁的核心代码是beanDefinitionMap.remove(beanName)

4.4 GenericApplicationContext

GenericApplicationContext 的注册和销毁其实都是委托DefaultListableBeanFactory实现的

private final DefaultListableBeanFactory beanFactory;

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {

    this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}

@Override
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
    this.beanFactory.removeBeanDefinition(beanName);
}