千家信息网

Spring Bean中Bean的实例化分析

发表于:2024-10-14 作者:千家信息网编辑
千家信息网最后更新 2024年10月14日,这篇文章主要介绍了Spring Bean中Bean的实例化分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring Bean中Bean的实例化分析文章都会有所收获,
千家信息网最后更新 2024年10月14日Spring Bean中Bean的实例化分析

这篇文章主要介绍了Spring Bean中Bean的实例化分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring Bean中Bean的实例化分析文章都会有所收获,下面我们一起来看看吧。

实例化前阶段

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)                        throws BeanCreationException {                //省略无关代码                try {               // 这里就是我们分析的重点了 ⭐️                        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);                        //⭐️ 注意这个逻辑:如果postProcessBeforeInstantiation方法返回非null 则将返回值作为创建的Bean。并中断正常的创建流程                        if (bean != null) {                                return bean;                        }                }                catch (Throwable ex) {                        //省略异常信息                }                try {                    //真正创建Bean的逻辑 实例化Bean对象,为Bean属性赋值等,这里暂不展开                        Object beanInstance = doCreateBean(beanName, mbdToUse, args);                        //省略日志输出                        return beanInstance;                }                catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {//省略异常信息        }

resolveBeforeInstantiation这个方法在BeanPostProcessor浅析 这一节分析过了 这里不再具体展开了。

如果InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 方法返回null,那么将不会中断正常Bean创建过程。
下面就来到的Bean实例化部分了。

实例化阶段

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {                //解析BeanClass,在BeanDefinition中类信息是以字符串形式展现,这里解析到字符串后 会将其加载为Class                Class beanClass = resolveBeanClass(mbd, beanName);                if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,                                        "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());                }                //如果设置了 Supplier 回调,则使用给定的回调方法初始化策略,通过获取Supplier#get得到实例化对象                 Supplier instanceSupplier = mbd.getInstanceSupplier();                if (instanceSupplier != null) {                        return obtainFromSupplier(instanceSupplier, beanName);                }           //如果工厂方法不为空,则使用工厂方法初始化                if (mbd.getFactoryMethodName() != null) {                        return instantiateUsingFactoryMethod(beanName, mbd, args);                }                                boolean resolved = false;                boolean autowireNecessary = false;                if (args == null) {           //加锁                        synchronized (mbd.constructorArgumentLock) {            //条件成立 说明构造函数或FactoryMethod已经被解析并被缓存,可直接利用构造函数解析           //与后面的SimpleInstantiationStrategy#instantiate呼应                                if (mbd.resolvedConstructorOrFactoryMethod != null) {                                        resolved = true;                                        autowireNecessary = mbd.constructorArgumentsResolved;                                }                        }                }    //如果已经被解析过                if (resolved) {          //条件成立 使用构造函数注入                        if (autowireNecessary) {                                return autowireConstructor(beanName, mbd, null, null);                        }                        else {        //使用默认构造函数解析                                return instantiateBean(beanName, mbd);                        }                }    // 使用SmartInstantiationAwareBeanPostProcessor 找到候选的构造函数 用于注入                Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);    // AutowireMode==AUTOWIRE_CONSTRUCTOR 条件成立 说明使用基于构造函数的注入方式 (默认是AUTOWIRE_NO,需要动态检测)    // mbd.hasConstructorArgumentValues() 条件成立 说明构造函数中拥有参数                if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||                                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {      //基于构造函数自动注入                        return autowireConstructor(beanName, mbd, ctors, args);                }                // 如果mbd中配置了构造函数 则使用它进行注入                ctors = mbd.getPreferredConstructors();                if (ctors != null) {                        return autowireConstructor(beanName, mbd, ctors, null);                }                // 使用默认构造函数实例化                return instantiateBean(beanName, mbd);        }

上面将doCreateBean精简一下,只暴露出我们比较关系的部分。一目了然,Bean的实例化过程就藏在createBeanInstance方法中。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {                //解析BeanClass,在BeanDefinition中类信息是以字符串形式展现,这里解析到字符串后 会将其加载为Class                Class beanClass = resolveBeanClass(mbd, beanName);                if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,                                        "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());                }                //如果设置了 Supplier 回调,则使用给定的回调方法初始化策略,通过获取Supplier#get得到实例化对象                 Supplier instanceSupplier = mbd.getInstanceSupplier();                if (instanceSupplier != null) {                        return obtainFromSupplier(instanceSupplier, beanName);                }           //如果工厂方法不为空,则使用工厂方法初始化                if (mbd.getFactoryMethodName() != null) {                        return instantiateUsingFactoryMethod(beanName, mbd, args);                }                                boolean resolved = false;                boolean autowireNecessary = false;                if (args == null) {           //加锁                        synchronized (mbd.constructorArgumentLock) {            //条件成立 说明构造函数或FactoryMethod已经被解析并被缓存,可直接利用构造函数解析           //与后面的SimpleInstantiationStrategy#instantiate呼应                                if (mbd.resolvedConstructorOrFactoryMethod != null) {                                        resolved = true;                                        autowireNecessary = mbd.constructorArgumentsResolved;                                }                        }                }    //如果已经被解析过                if (resolved) {          //条件成立 使用构造函数注入                        if (autowireNecessary) {                                return autowireConstructor(beanName, mbd, null, null);                        }                        else {        //使用默认构造函数解析                                return instantiateBean(beanName, mbd);                        }                }    // 使用SmartInstantiationAwareBeanPostProcessor 找到候选的构造函数 用于注入                Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);    // AutowireMode==AUTOWIRE_CONSTRUCTOR 条件成立 说明使用基于构造函数的注入方式 (默认是AUTOWIRE_NO,需要动态检测)    // mbd.hasConstructorArgumentValues() 条件成立 说明构造函数中拥有参数                if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||                                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {      //基于构造函数自动注入                        return autowireConstructor(beanName, mbd, ctors, args);                }                // 如果mbd中配置了构造函数 则使用它进行注入                ctors = mbd.getPreferredConstructors();                if (ctors != null) {                        return autowireConstructor(beanName, mbd, ctors, null);                }                // 使用默认构造函数实例化                return instantiateBean(beanName, mbd);        }

分析了上面的源码之后,我们试着总结一下上面代码主要完成的事情:

1、如果mbd配置了instanceSupplier回调,则使用instanceSupplier去初始化BeanDefinition

2、如果mbd配置了工厂方法,则使用工厂方法区初始化BeanDefinition

3、实例化BeanDefinition

  • 如果mbd已经被解析过了,则根据缓存 选择使用有参构造函数注入还是默认构造函数注入

  • 如果mbd没有被解析过,找到mbd中候选的构造函数(一个类可能有多个构造函数),再根据一些限定条件 选择是基于有参构造函数初始化还是默认构造函数初始化

针对第1点,其实就是lambda8 supplier接口的使用,不再介绍。

针对第3点,其实就是通过反射机制 创建实例对象,最终调用了SimpleInstantiationStrategy#instantiate方法

针对第2点 举例说明下 工厂方法静态工厂生成Bean的两种形式,再来展开说下instantiateUsingFactoryMethod源码。

配置Xml文件

                                
//实体对象@Datapublic class People implements Serializable {    private String name;    private Integer age;    public People() {    }    public static People createPeople() {        People people = new People();        people.setAge(18);        people.setName("我就是我");        return people;    }}//People工厂类public class PeopleFactory {    public People createPeople() {        return People.createPeople();    }}public class FactoryMethodDemo {    public static void main(String[] args) {        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("META-INF/spring.xml");        context.refresh();        People people = (People) context.getBean("staticFactoryMethod");        System.out.println(people);                People people = (People) context.getBean("instanceMethod");        System.out.println(people);                     context.close();    }}
public BeanWrapper instantiateUsingFactoryMethod(                        String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {                BeanWrapperImpl bw = new BeanWrapperImpl();                this.beanFactory.initBeanWrapper(bw);                Object factoryBean;                Class factoryClass;                boolean isStatic;                //获取FactoryBeanName,实例方法与静态工厂方法的区别就在于有没有FactoryBeanName                String factoryBeanName = mbd.getFactoryBeanName();                if (factoryBeanName != null) {      //如果存在FactoryBeanName,则说明是实例方法                        if (factoryBeanName.equals(beanName)) {                                throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,                                                "factory-bean reference points back to the same bean definition");                        }      //获取当前factoryBeanName名称的Bean                        factoryBean = this.beanFactory.getBean(factoryBeanName);                        if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {                                throw new ImplicitlyAppearedSingletonException();                        }      //获取工厂类Class                        factoryClass = factoryBean.getClass();      //标记为非静态                        isStatic = false;                }                else {                        // 走到这里,说明是静态工厂方法                        if (!mbd.hasBeanClass()) {                                throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,                                                "bean definition declares neither a bean class nor a factory-bean reference");                        }      //factoryBean设置为null                        factoryBean = null;      //获取工厂类Class,这里使用BeanDefinition作为其工厂类                        factoryClass = mbd.getBeanClass();      //标记为非静态                        isStatic = true;                }                Method factoryMethodToUse = null;                ArgumentsHolder argsHolderToUse = null;                Object[] argsToUse = null;                //explicitArgs 这个是getBean方法传递过来的,一般为null                if (explicitArgs != null) {                        argsToUse = explicitArgs;                }                else {                        Object[] argsToResolve = null;      //加锁                        synchronized (mbd.constructorArgumentLock) {        //获取被解析的工厂方法                                factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;        //条件成立 说明工厂方法已经被解析过了,并存到了mbd中缓存起来了                                if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {                                        // Found a cached factory method...                                        argsToUse = mbd.resolvedConstructorArguments;                                        if (argsToUse == null) {                                                argsToResolve = mbd.preparedConstructorArguments;                                        }                                }                        }                        if (argsToResolve != null) {                                argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);                        }                }                if (factoryMethodToUse == null || argsToUse == null) {      //获取工厂类                        factoryClass = ClassUtils.getUserClass(factoryClass);                        //获取类中的方法                        Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);                        List candidateList = new ArrayList<>();                        for (Method candidate : rawCandidates) {        //如果方法修饰符包含static,并且方法名称是配置的FactoryMethod,则添加到候选集合中                                if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {                                        candidateList.add(candidate);                                }                        }                  //如果候选集合有1个元素 并且BeanDefinition中未设置构造参数 (explicitArgs一般都为null )                        if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {        //获取方法                                Method uniqueCandidate = candidateList.get(0);        //如果方法参数为空                                if (uniqueCandidate.getParameterCount() == 0) {                                        mbd.factoryMethodToIntrospect = uniqueCandidate;                                        synchronized (mbd.constructorArgumentLock) {            //将下面这些全缓存到mbd中,下次直接用(与createBeanInstance方法呼应上了)                                                mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;                                                mbd.constructorArgumentsResolved = true;                                                mbd.resolvedConstructorArguments = EMPTY_ARGS;                                        }          //实例化bd,设置到BeanWrapper中                                        bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));                                        return bw;                                }                        }                        //程序走到这里 大概率是BeanDefinition中设置了构造参数                        Method[] candidates = candidateList.toArray(new Method[0]);      //按照修饰符及方法参数 进行排序                        AutowireUtils.sortFactoryMethods(candidates);                        ConstructorArgumentValues resolvedValues = null;      //是否构造函数注入                        boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);                        int minTypeDiffWeight = Integer.MAX_VALUE;                        Set ambiguousFactoryMethods = null;      //最小参数数量 默认是0                        int minNrOfArgs;                        if (explicitArgs != null) {                                minNrOfArgs = explicitArgs.length;                        }                        else {        //走到这里 说明explicitArgs未被设置参数        //如果bd设置了构造参数,则从bd中解析参数                                if (mbd.hasConstructorArgumentValues()) {                                        ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();                                        resolvedValues = new ConstructorArgumentValues();          //得到解析的最小参数数量                                        minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);                                }                                else {                                        minNrOfArgs = 0;                                }                        }                        LinkedList causes = null;                        //下面主要是推断参数、FactoryMethod,代码比较长 就先不分析了                        for (Method candidate : candidates) {                                Class[] paramTypes = candidate.getParameterTypes();                                if (paramTypes.length >= minNrOfArgs) {                                        ArgumentsHolder argsHolder;                                        if (explicitArgs != null) {                                                // Explicit arguments given -> arguments length must match exactly.                                                if (paramTypes.length != explicitArgs.length) {                                                        continue;                                                }                                                argsHolder = new ArgumentsHolder(explicitArgs);                                        }                                        else {                                                // Resolved constructor arguments: type conversion and/or autowiring necessary.                                                try {                                                        String[] paramNames = null;                                                        ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();                                                        if (pnd != null) {                                                                paramNames = pnd.getParameterNames(candidate);                                                        }                                                        argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,                                                                        paramTypes, paramNames, candidate, autowiring, candidates.length == 1);                                                }                                                catch (UnsatisfiedDependencyException ex) {                                                        if (logger.isTraceEnabled()) {                                                                logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);                                                        }                                                        // Swallow and try next overloaded factory method.                                                        if (causes == null) {                                                                causes = new LinkedList<>();                                                        }                                                        causes.add(ex);                                                        continue;                                                }                                        }                                        int typeDiffWeight = (mbd.isLenientConstructorResolution() ?                                                        argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));                                        // Choose this factory method if it represents the closest match.                                        if (typeDiffWeight < minTypeDiffWeight) {                                                factoryMethodToUse = candidate;                                                argsHolderToUse = argsHolder;                                                argsToUse = argsHolder.arguments;                                                minTypeDiffWeight = typeDiffWeight;                                                ambiguousFactoryMethods = null;                                        }                                        // Find out about ambiguity: In case of the same type difference weight                                        // for methods with the same number of parameters, collect such candidates                                        // and eventually raise an ambiguity exception.                                        // However, only perform that check in non-lenient constructor resolution mode,                                        // and explicitly ignore overridden methods (with the same parameter signature).                                        else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&                                                        !mbd.isLenientConstructorResolution() &&                                                        paramTypes.length == factoryMethodToUse.getParameterCount() &&                                                        !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {                                                if (ambiguousFactoryMethods == null) {                                                        ambiguousFactoryMethods = new LinkedHashSet<>();                                                        ambiguousFactoryMethods.add(factoryMethodToUse);                                                }                                                ambiguousFactoryMethods.add(candidate);                                        }                                }                        }                        if (factoryMethodToUse == null) {                                if (causes != null) {                                        UnsatisfiedDependencyException ex = causes.removeLast();                                        for (Exception cause : causes) {                                                this.beanFactory.onSuppressedException(cause);                                        }                                        throw ex;                                }                                List argTypes = new ArrayList<>(minNrOfArgs);                                if (explicitArgs != null) {                                        for (Object arg : explicitArgs) {                                                argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");                                        }                                }                                else if (resolvedValues != null) {                                        Set valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());                                        valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());                                        valueHolders.addAll(resolvedValues.getGenericArgumentValues());                                        for (ValueHolder value : valueHolders) {                                                String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :                                                                (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));                                                argTypes.add(argType);                                        }                                }                                String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);                                //抛出异常                        }                        else if (void.class == factoryMethodToUse.getReturnType()) {                                //抛出异常                        }                        else if (ambiguousFactoryMethods != null) {                                //抛出异常                        }                        if (explicitArgs == null && argsHolderToUse != null) {                                mbd.factoryMethodToIntrospect = factoryMethodToUse;                                argsHolderToUse.storeCache(mbd, factoryMethodToUse);                        }                }                Assert.state(argsToUse != null, "Unresolved factory method arguments");    //实例化bd 设置到BeanWrapper中                bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));                return bw;        }

至此经过createBeanInstance方法 就为我们创建了一个实例对象,但是现在这个对象属性还未被赋值。

实例化后阶段

实例对象创建之后,就来到了对象属性赋值过程了,我们大致看一下populateBean方法,观察下InstantiationAwareBeanPostProcessor对属性赋值过程的影响

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {                //省略无关代码                boolean continueWithPropertyPopulation = true;                //条件一 synthetic默认值是false 一般都会成立                //条件二 成立的话 说明存在InstantiationAwareBeanPostProcessor                if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {                        for (BeanPostProcessor bp : getBeanPostProcessors()) {                                if (bp instanceof InstantiationAwareBeanPostProcessor) {                                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;                                        //在BeanPostProcessor浅析中分析到此方法时说过,若Bean实例化后回调不返回true 则对属性赋值过程产生影响。以下代码就是说明                                        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {                                                continueWithPropertyPopulation = false;                                                break;                                        }                                }                        }                }                //ibp.postProcessAfterInstantiation=false时 属性赋值过程终止                if (!continueWithPropertyPopulation) {                        return;                }

关于"Spring Bean中Bean的实例化分析"这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对"Spring Bean中Bean的实例化分析"知识都有一定的了解,大家如果还想学习更多知识,欢迎关注行业资讯频道。

0