转载

深度解析 Spring Bean 的加载

点击上方 "IT牧场" ,选择 "设为星标"

技术干货每日送达!

1、getBean()

这个方法有点长我们进行分段解析。

1.1、从缓存获取

 1//提取对应的beanName
2final String beanName = transformedBeanName(name);
3Object bean;
4
5// Eagerly check singleton cache for manually registered singletons.
6/**
7 * 检查缓存中或者实例工厂中是否有对应实例
8 * 为何会首先使用这段代码
9 * 因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
10 * Spring创建Bean的原则是不等bean创建完成就会将创建Bean的ObjectFactory提早曝光
11 * 也就是讲ObjectFactory加入到缓存中,一旦下一个bean创建的时候需要依赖上个bean则直接使用ObjectFactory
12 */

13//尝试从混成或者singletonFactories中的ObjectFactory中获取
14Object sharedInstance = getSingleton(beanName);
15if (sharedInstance != null && args == null) {
16 if (logger.isDebugEnabled()) {
17 if (isSingletonCurrentlyInCreation(beanName)) {
18 logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
19 "' that is not fully initialized yet - a consequence of a circular reference");
20 }
21 else {
22 logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
23 }
24 }
25
26 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
27}

这个方法首先从缓存中去获取,这个时候缓存中当然没有数据,因为此时是初始化,我们还没有将bean方到singletonObjects这个map中去,如下图代码。

1.1.1、getSingleton()

 1@Nullable
2protected Object getSingleton(String beanName, boolean allowEarlyReference) {
3 //检查缓存中是否存在实例
4 Object singletonObject = this.singletonObjects.get(beanName);
5 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
6 //若不存在则锁定全局变量进行处理
7 synchronized (this.singletonObjects) {
8 singletonObject = this.earlySingletonObjects.get(beanName);
9 if (singletonObject == null && allowEarlyReference) {
10 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
11 if (singletonFactory != null) {
12 //调用预先设定的getObject方法
13 singletonObject = singletonFactory.getObject();
14 //记录在缓存中,earlySingletonObjects和singletonFactories互斥
15 this.earlySingletonObjects.put(beanName, singletonObject);
16 this.singletonFactories.remove(beanName);
17 }
18 }
19 }
20 }
21 return (singletonObject != NULL_OBJECT ? singletonObject : null);
22}

1.2、获取BEANFACOTRY

 1if (isPrototypeCurrentlyInCreation(beanName)) {
2 throw new BeanCurrentlyInCreationException(beanName);
3}
4
5// Check if bean definition exists in this factory.
6//如果beaDefinitionMap中也就是在所有已经加载的类中不包括beanName则尝试从parentBeanFactory中检测
7BeanFactory parentBeanFactory = getParentBeanFactory();
8if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
9 // Not found -> check parent.
10 String nameToLookup = originalBeanName(name);
11 if (parentBeanFactory instanceof AbstractBeanFactory) {
12 return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
13 nameToLookup, requiredType, args, typeCheckOnly);
14 }
15 else if (args != null) {
16 //递归到BeanFactory中去寻找
17 // Delegation to parent with explicit args.
18 return (T) parentBeanFactory.getBean(nameToLookup, args);
19 }
20 else {
21 // No args -> delegate to standard getBean method.
22 return parentBeanFactory.getBean(nameToLookup, requiredType);
23 }
24}

这段代码首先获取该bean的父类,若有父类则用父类去实例化该bean,这里的parentBeanFactory为null,暂时不做考虑。接下来看第三部分。

1.3

 1//如果不是做类型检查则是创建bean,这里要进行记录
2//第一部分
3if (!typeCheckOnly) {
4 markBeanAsCreated(beanName);
5}
6//第二部分
7try {
8 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
9 checkMergedBeanDefinition(mbd, beanName, args);
10
11 // Guarantee initialization of beans that the current bean depends on.
12 String[] dependsOn = mbd.getDependsOn();
13 //若存在依赖则需要递归实例化依赖的bean
14 if (dependsOn != null) {
15 for (String dep : dependsOn) {
16 if (isDependent(beanName, dep)) {
17 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
18 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
19 }
20 registerDependentBean(dep, beanName);
21 getBean(dep);
22 }
23 }
24//第三部分
25 // Create bean instance.
26 //实例化依赖的bean之后可以实例化mbd本身了
27 //单例模式的创建
28 if (mbd.isSingleton()) {
29 sharedInstance = getSingleton(beanName, () -> {
30 try {
31 /**
32 *核心创建bean
33 */

34 return createBean(beanName, mbd, args);
35 }
36 catch (BeansException ex) {
37 // Explicitly remove instance from singleton cache: It might have been put there
38 // eagerly by the creation process, to allow for circular reference resolution.
39 // Also remove any beans that received a temporary reference to the bean.
40 destroySingleton(beanName);
41 throw ex;
42 }
43 });
44 //真正的bean初始化处理
45 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
46 }
  • 1、第一部分,标记目前的bean属于正在创建状态

  • 2、第二部分,根据beanName获取该bean在beanFactory中的beanDefinitionMap中beanDefinition,然后获取该bean所依赖的bean(此处是spring解决循环依赖的关键),如果依赖的bean还未创建,则先创建依赖的bean,依次递归调用(DI依赖注入的概念),如果找不到依赖,则忽略。

  • 3、若是单例,创建bean,调用CreateBean()方法,此处只考虑单例模式

接下来跟踪createBean()方法。此处调用的是AbstractAutowireCapableBeanFactory中的方法

1.4、CREATEBEAN()

 1//第一部分
2if (logger.isDebugEnabled()) {
3 logger.debug("Creating instance of bean '" + beanName + "'");
4}
5RootBeanDefinition mbdToUse = mbd;
6
7// Make sure bean class is actually resolved at this point, and
8// clone the bean definition in case of a dynamically resolved Class
9// which cannot be stored in the shared merged bean definition.
10/**
11 * 锁定class,根据设置的class属性或者根据classname来解析class
12 */

13Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
14if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
15 mbdToUse = new RootBeanDefinition(mbd);
16 mbdToUse.setBeanClass(resolvedClass);
17}
18//第二部分
19//验证及准备覆盖的方法
20try {
21 mbdToUse.prepareMethodOverrides();
22}
23catch (BeanDefinitionValidationException ex) {
24 throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
25 beanName, "Validation of method overrides failed", ex);
26}
27//第三部分
28try {
29 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
30 //给BeanPostProcessors一个机会来返回代理来代替真正的实例,前置处理器
31 Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
32 /**
33 * 前置处理后返回结果不为空,直接返回结果,AOP功能就是基于这里判断的
34 */

35 if (bean != null) {
36 return bean;
37 }
38}
39catch (Throwable ex) {
40 throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
41 "BeanPostProcessor before instantiation of bean failed", ex);
42}
43//第四部分
44try {
45 Object beanInstance = doCreateBean(beanName, mbdToUse, args);
46 if (logger.isDebugEnabled()) {
47 logger.debug("Finished creating instance of bean '" + beanName + "'");
48 }
49 return beanInstance;
50}
  • 1、第一部分:确保该bean的class是真实存在的,也就是该bean是可以classload可以找到加载的,若不存在则放入beanDefination中

  • 2、第二部分:准备方法的重写

  • 3、第三部分:(重要)最后的return就是返回的bean,但看注释:Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.这边就很清晰了,我们以前在beanPostProcessor的章节讲过,beanPostProcessor是可以临时修改bean的,它的优先级高于正常实例化bean的(也就是第四部分实例化的方法)如果beanPostProcessor能返回,则直接返回了,这边代码下次分析,我们还是先分析主要流程:

  • 4、doCreateBean(beanName, mbd, args)这个方法,接下来看这个

     1BeanWrapper instanceWrapper = null;
    2if (mbd.isSingleton()) {
    3 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    4}
    5if (instanceWrapper == null) {
    6 //根据指定的bean使用对应的侧脸创建新的实例,如工厂方法,构造函数自动注入,简单初始化
    7 instanceWrapper = createBeanInstance(beanName, mbd, args);
    8}
    9final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    10Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    11mbd.resolvedTargetType = beanType;
    12
    13if (beanType != null) {
    14 // Allow post-processors to modify the merged bean definition.
    15 synchronized (mbd.postProcessingLock) {
    16 if (!mbd.postProcessed) {
    17 try {
    18 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    19 }
    20 catch (Throwable ex) {
    21 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    22 "Post-processing of merged bean definition failed", ex);
    23 }
    24 mbd.postProcessed = true;
    25 }
    26 }
    27}

这里首先初始化一个instanceWrapper,然后再看createBeanInstance()

 1protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
2 // Make sure bean class is actually resolved at this point.
3 Class<?> beanClass = resolveBeanClass(mbd, beanName);
4
5 if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
6 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
7 "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
8 }
9
10 Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
11 if (instanceSupplier != null) {
12 return obtainFromSupplier(instanceSupplier, beanName);
13 }
14
15 if (mbd.getFactoryMethodName() != null) {
16 return instantiateUsingFactoryMethod(beanName, mbd, args);
17 }
18
19 // Shortcut when re-creating the same bean...
20 boolean resolved = false;
21 boolean autowireNecessary = false;
22 if (args == null) {
23 synchronized (mbd.constructorArgumentLock) {
24 if (mbd.resolvedConstructorOrFactoryMethod != null) {
25 resolved = true;
26 autowireNecessary = mbd.constructorArgumentsResolved;
27 }
28 }
29 }
30 if (resolved) {
31 if (autowireNecessary) {
32 return autowireConstructor(beanName, mbd, null, null);
33 }
34 else {
35 return instantiateBean(beanName, mbd);
36 }
37 }
38
39 // Need to determine the constructor...
40 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
41 if (ctors != null ||
42 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
43 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
44 return autowireConstructor(beanName, mbd, ctors, args);
45 }
46
47 // No special handling: simply use no-arg constructor.
48 return instantiateBean(beanName, mbd);
49}

这块代码主要是再次对bean做安全检查并确定该bean有默认的构造函数,createBeanInstance()这个方法最后一行

 1protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
2 try {
3 Object beanInstance;
4 final BeanFactory parent = this;
5 if (System.getSecurityManager() != null) {
6 beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
7 getInstantiationStrategy().instantiate(mbd, beanName, parent),
8 getAccessControlContext());
9 }
10 else {
11 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
12 }
13 BeanWrapper bw = new BeanWrapperImpl(beanInstance);
14 initBeanWrapper(bw);
15 return bw;
16 }
17 catch (Throwable ex) {
18 throw new BeanCreationException(
19 mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
20 }
21}

然后我们再回到doCreateBean()这个方法,在AbstractAutowireCapableBeanFactory

 1// Initialize the bean instance.
2Object exposedObject = bean;
3try {
4 //对bean进行填充,将各个属性值注入,其中,可能存在依赖与其他bean的属性,则会递归初始依赖bean
5 populateBean(beanName, mbd, instanceWrapper);// sunliang marked
6 if (exposedObject != null) {
7 //调用初始化方法,比如init-method
8 exposedObject = initializeBean(beanName, exposedObject, mbd);
9 }
10}

初始化bean,的确,现在bean已经实例化了,开始初始化该bean,进入initializeBean(…)这个方法

1if (System.getSecurityManager() != null) {
2 AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
3 invokeAwareMethods(beanName, bean);
4 return null;
5 }, getAccessControlContext());
6}
7else {
8 invokeAwareMethods(beanName, bean);
9}

接下来进入到invokeAwareMethods()方法

 1private void invokeAwareMethods(final String beanName, final Object bean) {
2 if (bean instanceof Aware) {
3 if (bean instanceof BeanNameAware) {
4 ((BeanNameAware) bean).setBeanName(beanName);
5 }
6 if (bean instanceof BeanClassLoaderAware) {
7 ClassLoader bcl = getBeanClassLoader();
8 if (bcl != null) {
9 ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
10 }
11 }
12 if (bean instanceof BeanFactoryAware) {
13 ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
14 }
15 }
16}

再回到initializeBean()方法中

 1try {
2 invokeInitMethods(beanName, wrappedBean, mbd);
3}
4protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
5 throws Throwable
{
6
7 boolean isInitializingBean = (bean instanceof InitializingBean);
8 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
9 if (logger.isDebugEnabled()) {
10 logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
11 }
12 if (System.getSecurityManager() != null) {
13 try {
14 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
15 ((InitializingBean) bean).afterPropertiesSet();
16 return null;
17 }, getAccessControlContext());
18 }
19 catch (PrivilegedActionException pae) {
20 throw pae.getException();
21 }
22 }
23 else {
24 //第一部分
25 ((InitializingBean) bean).afterPropertiesSet();
26 }
27 }
28
29 if (mbd != null) {
30 String initMethodName = mbd.getInitMethodName();
31 if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
32 !mbd.isExternallyManagedInitMethod(initMethodName)) {
33 //第二部分
34 invokeCustomInitMethod(beanName, bean, mbd);
35 }
36 }
37}

首先先判断该bean是否实现了InitializingBean,如果实现了先执行afterPropertiesSet这个方法,然后如果该bean又执行了init-method,到此我们的bean创建和加载算是基本完成,下一节分析一些具体详细点的实现。

干货分享

最近将个人学习笔记整理成册,使用PDF分享。关注我,回复如下代码,即可获得百度盘地址,无套路领取!

001:《Java并发与高并发解决方案》学习笔记; 002:《深入JVM内核——原理、诊断与优化》学习笔记; 003:《Java面试宝典》 004:《Docker开源书》 005:《Kubernetes开源书》 006:《DDD速成(领域驱动设计速成)》 007: 全部 008: 加技术讨论群

近期热文

想知道更多?长按/扫码关注我吧↓↓↓ 深度解析 Spring Bean 的加载 >>>技术讨论群<<< 喜欢就点个 "在看" 呗^_^

原文  http://mp.weixin.qq.com/s?__biz=MzI4ODQ3NjE2OA==&mid=2247485464&idx=2&sn=3c54bc0d9bdca308b31a1222d8edc58d
正文到此结束
Loading...