服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Spring Bean生命周期之Bean的实例化详解

Spring Bean生命周期之Bean的实例化详解

2022-08-24 11:37码农的进阶之路 Java教程

这篇文章主要为大家详细介绍了Spring Bean生命周期之Bean的实例化,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

前言

上一节说到了BeanDefinition的合并过程,这节该说Bean的实例化过程了。根据AbstractAutowireCapableBeanFactory#createBean源码逻辑 可将实例化过程分为实例化前阶段实例化过程实例化后阶段

实例化前阶段

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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实例化部分了。

实例化阶段

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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方法中。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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文件

?
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="peopleFactory" class="com.wojiushiwo.factorymethod.PeopleFactory"/>
    <!--实例方法-->
    <bean id="instanceMethod" factory-bean="peopleFactory" factory-method="createPeople"/>
        <!--静态方法-->
    <bean id="staticFactoryMethod" class="com.wojiushiwo.factorymethod.People" factory-method="createPeople"/>
</beans>
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//实体对象
@Data
public 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();
    }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
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<Method> 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<Method> 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<UnsatisfiedDependencyException> 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<String> argTypes = new ArrayList<>(minNrOfArgs);
                if (explicitArgs != null) {
                    for (Object arg : explicitArgs) {
                        argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
                    }
                }
                else if (resolvedValues != null) {
                    Set<ValueHolder> 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对属性赋值过程的影响

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
        }

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注服务器之家的更多内容!   

原文链接:https://blog.csdn.net/zyxwvuuvwxyz/article/details/123253043

延伸 · 阅读

精彩推荐