精华内容
下载资源
问答
  • spring装载bean
    2019-12-04 21:54:14

    如何把一个对象放到Spring容器,交由Spring管理? 

     

    1. 加@Component
    2. @Import(xx)导入(用于第三方的类)
    3. 定义一个FactoryBean(实现FactroyBean接口)(用于第三方的类)
    4. 调用BeanFactory的registerSingleton()注册一个对象(用于第三方的类)

     

     @Component

    @Component
    public class B {
    
        public B(){
            System.out.println("B start");
        }
    }

    定义一个FactoryBean(实现FactroyBean接口)

    public class MyFactoryBean implements FactoryBean {
        @Override
        public Object getObject() throws Exception {
            return new B();
        }
    
        @Override
        public Class<?> getObjectType() {
            return B.class;
        }
    
        @Override
        public boolean isSingleton() {
            return true;
        }
    }

    调用BeanFactory的registerSingleton()注册一个对象

     AnnotationConfigApplicationContext applicationContext = new 
     AnnotationConfigApplicationContext(MyConfig.class);
     applicationContext.getBeanFactory().registerSingleton("b",new B());

    此方法也是把一个对象交由Spring容器管理,但这样确实有些鸡肋。之所以把一个对象交由Spring管理,主要是解决对象之间的依赖关系。如果我们手动调用这个API,这个对象,确实放到spring容器当中了,但,之前放到Spring容器中的对象就不能用得到这个对象(API注册的)的依赖,因为他们先一步放到容器中,此时调用API的这个对象还没交由Spring容器管理。

    下面在看一种情况:

     AnnotationConfigApplicationContext applicationContext = new 
     AnnotationConfigApplicationContext();     
     applicationContext.getBeanFactory().registerSingleton("b",new B());
     applicationContext.register(MyConfig.class);
     applicationContext.refresh();

    这样做,只是把调用API方式的时机放到Spring容器初始化之前了,但这个对象却不能用到后面由Spring管理的对象的依赖。

     

    更多相关内容
  • spring加载bean的流程

    千次阅读 2021-10-15 19:28:47
    BeanPostProcessor:后置处理bean,它是bean级别的,可以在springbean的初始化前后对bean进行增强。使用时直接实现这个接口,然后加到ioc容器中即可。 BeanFactoryPostProcessor:他可以对springbean的对bean...

    BeanPostProcessor和BeanFactoryPostProcessor的区别

    这两个都是后处理bean的接口

    1. BeanPostProcessor:后置处理bean,它是bean级别的,可以在springbean的初始化前后对bean进行增强。使用时直接实现这个接口,然后加到ioc容器中即可。
      在这里插入图片描述
    2. BeanFactoryPostProcessor:他可以对springbean的对beanDefinition进行修改等相关操作,比如可以将beanname为aa指向A对象改为指向B对象。
      在这里插入图片描述

    javabean和springbean的区别

    1. javabean(java对象):使用new或者其他方式直接创建,由jvm统一管理。一个java对象就只有类中定义的属性和方法。
    2. springbean:通过反射创建、由Spring容器统一管理。除了拥有类中的属性和方法之外还有spring给他增加或者修改的属性和方法。

    springbean的加载流程

    1. 首先、java类通过类加载器加载成字节码文件也就是Class对象
    2. 然后根据bean的字节码文件生成一个BeanDefinition(beanDefinition被称为bean的定义类、这个类里面放了bean的类信息和类的其他配置信息)
    3. 生成beanDefinition后会放到一个beanDefinitionMap里面
    4. 然后会将beanDefinitionMap里面的所有beanDefiinition遍历检查一遍、遍历之前会执行BeanFactoryPostProcessor对beanDefinition进行修改等相关操作,再判断类名等配置信息是否合法
    5. 检查完之后符合要求的他就会去创建这个对象了、创建对象时会执行BeanPostProcessor方法,进行属性注入、初始化方法、AOP处理等等。
    6. 创建完之后就会放到一个叫singletonObjects中

    在这里插入图片描述

    展开全文
  • 通过前面两节的学习我们已经知道了Spring是如何解析XML与装载BeanDefinition的;在本章节中我们将继续学习bean的装载过程这将会面临更大的挑战,bean加载的功能实现远比bean的解析要复杂得多,不过没关系,步步深入...

    前言

    通过前面两节的学习我们已经知道了Spring是如何解析XML与装载BeanDefinition的;在本章节中我们将继续学习bean的装载过程这将会面临更大的挑战,bean加载的功能实现远比bean的解析要复杂得多,不过没关系,步步深入层层解析终将会有收获。我们还是以一个例子开始:

    BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("application.xml"));
    User user = (User)beanFactory.getBean("user");
    

    bean的加载

    我们在idea中跟踪getBean("user")进一步探秘,最后来到了我们想看到的AbstractBeanFactory#doGetBean();所以今天的内容将从此开始,我们先贴出该方法的主要代码:

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    		// 1.提取对应的 beanName
    		final String beanName = transformedBeanName(name);
    		Object bean;
    		/* *
    		 *检査缓存中或者实例工厂中是否有对应的实例
    		 *为什么首先会使用这段代码呢,
    		 *因为在创建单例 bean 的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环			依赖,
    		 * Spring 创建 bean 的原则是不等 bean 创建完成就会将创建 bean 的 					ObjectFactory 提早曝光
    		 *也就是将 ObjectFactory 加入到缓存中,一旦下个 bean 创建时候需要依赖上个 			bean 则直接使用 ObjectFactory
    		 */
    		// 2.直接尝试从缓存获取或者 singletonFactories 中的 ObjectFactory 中获取
    		Object sharedInstance = getSingleton(beanName);
    		if (sharedInstance != null && args == null) {
    			if (logger.isDebugEnabled()) {
    				if (isSingletonCurrentlyInCreation(beanName)) {
    					logger.debug(".....");
    				} else {
    					logger.debug(".....");
    				}
    			}
    			// 3.返回对应的实例,有时候存在诸如 BeanFactory 的情况并不是直接返回实例本身而是返回指定方法返回的实例 bean
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    		} else {
    			// Fail if we're already creating this bean instance:
    			// We're assumably within a circular reference.
    			// 指定的bean是否正在创建中
    			if (isPrototypeCurrentlyInCreation(beanName)) {
    				throw new BeanCurrentlyInCreationException(beanName);
    			}
    			// 检查该工厂中是否存在bean定义
    			// Check if bean definition exists in this factory.
    			BeanFactory parentBeanFactory = getParentBeanFactory();
    			// //如果 beanDefinitionMap 中也就是在所有已经加载的类中不包括 beanName 则尝试从
    			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    				// Not found -> check parent.
    				//parentBeanFactory 中检测
    				String nameToLookup = originalBeanName(name);
    				if (parentBeanFactory instanceof AbstractBeanFactory) {
    					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
    							nameToLookup, requiredType, args, typeCheckOnly);
    				} else if (args != null) {
    					// Delegation to parent with explicit args. 使用显式参数委派给父级
    					return (T) parentBeanFactory.getBean(nameToLookup, args);
    				} else {
    					// No args -> delegate to standard getBean method.
    					return parentBeanFactory.getBean(nameToLookup, requiredType);
    				}
    			}
    			// 如果不是仅仅做类型检查则是创建 bean,这里要进行记录
    			if (!typeCheckOnly) {
    				markBeanAsCreated(beanName);
    			}
    
    			try {
    				// 4.将存储 XML 配置文件的 GernericBeanDefinition 转换为 RootBeanDefinition
    				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    				// 如果指定BeanName 是子 Bean 的话同时会合并父类 的相关属性
    				checkMergedBeanDefinition(mbd, beanName, args);
    				// Guarantee initialization of beans that the current bean depends on.
    				String[] dependsOn = mbd.getDependsOn();
    				// 若的 存在依赖则需要递归实例化依赖的 bean
    				if (dependsOn != null) {
    					for (String dep : dependsOn) {
    						if (isDependent(beanName, dep)) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"......'");
    						}
    						//缓存依赖调用
    						registerDependentBean(dep, beanName);
    						try {
    							getBean(dep);
    						} catch (NoSuchBeanDefinitionException ex) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"......", ex);
    						}
    					}
    				}
    				// Create bean instance.
    				// 5.实例化依赖的 bean  后便可以实例化 mbd
    				if (mbd.isSingleton()) {
    					// 单例模式的创建
    					sharedInstance = getSingleton(beanName, () -> {
    						try {
    							// 创建bean
    							return createBean(beanName, mbd, args);
    						} catch (BeansException ex) {
    							destroySingleton(beanName);
    							throw ex;
    						}
    					});
    					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    					 // 创建 多例的bean
    				} else if (mbd.isPrototype()) {
    					// It's a prototype -> create a new instance.
    					Object prototypeInstance = null;
    					try {
    						beforePrototypeCreation(beanName);
    						prototypeInstance = createBean(beanName, mbd, args);
    					} finally {
    						afterPrototypeCreation(beanName);
    					}
    					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    				} else {
    					String scopeName = mbd.getScope();
    					// 指定的 scope  上实例化bean
    					final Scope scope = this.scopes.get(scopeName);
    					if (scope == null) {
    						throw new IllegalStateException("......");
    					}
    					try {
    						Object scopedInstance = scope.get(beanName, () -> {
    							beforePrototypeCreation(beanName);
    							try {
    								return createBean(beanName, mbd, args);
    							} finally {
    								afterPrototypeCreation(beanName);
    							}
    						});
    						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    					} catch (IllegalStateException ex) {
    						throw new BeanCreationException(beanName,
    								"......",
    								ex);
    					}
    				}
    			} catch (BeansException ex) {
    				cleanupAfterBeanCreationFailure(beanName);
    				throw ex;
    			}
    		}
    		// // 检査需要的类型是否符合 bean
    		// Check if required type matches the type of the actual bean instance.
    		if (requiredType != null && !requiredType.isInstance(bean)) {
    			try {
    				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
    				if (convertedBean == null) {
    					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    				}
    				return convertedBean;
    			} catch (TypeMismatchException ex) {
    				if (logger.isDebugEnabled()) {
    					logger.debug("......", ex);
    				}
    				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    			}
    		}
    		return (T) bean;
    	}
    

    我们来总结一下这一段代码都干了什么;

    1. 转换对应beanName

    或许很多人不理解转换对应beanName是什么意思,传入的参数name不就是beanName 吗?其实不是,这里传入的参数可能是别名,也可能是FactoryBean,所以需要进行一系列的 解析,这些解析内容包括如下内容。
    去除FactoryBean的修饰符,也就是如果name="&aa"那么会首先去除&而使name="aa"取指定alias所表示的最终beanName,例如别名A指向名称为B的bean则返回B; 若别名A指向别名B,别名B又指向名称为C的bean则返回C。

    1. 尝试从缓存中加载单例
      单例在Spring的同一个容器内只会被创建一次,后续再获取bean,就直接从单例缓存中获 取了。当然这里也只是尝试加载,首先尝试从缓存中加载,如果加载不成功则再次尝试从 singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖 的时候为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完成就会将创建bean 的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直 接使用ObjectFactory (后面章节会对循环依赖重点讲解)。

    2. bean的实例化
      如果从缓存中得到了 bean的原始状态,则需要对bean进行实例化。这里有必要强调一下, 缓存中记录的只是最原始的bean状态,并不一定是我们最终想要的bean。举个例子,假如我 们需要对工厂bean进行处理,那么这里得到的其实是工厂bean的初始状态,但是我们真正需 要的是工厂bean中定义的factory-method方法中返回的bean,而getObjectForBeanlnstance就 是完成这个工作的,后续会详细讲解。

    3. 原型模式的依赖检查

    只有在单例情况下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性, 那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A, 造成循环依赖,也就是情况:isPrototypeCurrentlylnCreation(beanName)判断 true

    1. 检测parentBeanFactory

    从代码上看,如果缓存没有数据的话直接转到父类工厂上去加载了,这是为什么呢?

    可能读者忽略了一个币要的判断条件:parentBeanFactory!=null&&IcontainsBean Definition (beanName), parentBeanFactory != null parentBeanFactory如果为空,则其他一切都是浮云, 这个没什么说的,但是!containsBeanDefinition(beanName)就比较重要了,它是在检测如果当前 加载的XML配置文件中不包含beanName所对应的配置,就只能到parentBeanFactory去尝试然后再去递归的调用getBean方法。

    1. 将存储XML配置文件的GernericBeanDefinition转换为 RootBeanDefinition

    因为从XML配置文件中读取到的bean信息是存储在GernericBeanDefinition中的,但是所 有的bean后续处理都是针对于RootBeanDefinition的,所以这里需要进行一个转换,转换的同时 如果父类bean不为空的话,则会一并合并父类的属性。

    1. 寻找依赖

    因为bean的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并 且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的 加载顺寻中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖。

    1. 针对不同的scope进行bean的创建

    我们都知道,在Spring中存在着不同的scope,其中默认的是singleton,但是还有些其他 的配置诸如prototype、request之类的。在这个步骤中,Spring会根据不同的配置进行不同的初 始化策略。

    1. 类型转换

    程序到这里返回bean后已经基本结束了,通常对该方法的调用参数requiredType是为空的, 但是可能会存在这样的情况,返回的bean其实是个String,但是requiredType却传入Integer 类型,那么这时候本步骤就会起作用了,它的功能是将返回的bean转换为requiredType所指定 的类型。当然,String转换为Integer是最简单的一种转换,在Spring中提供了各种各样的转换 器,用户也可以自己扩展转换器来满足需求。

    经过上面的步骤后bean的加载就结束了,这个时候就可以返回我们所需要的bean 了;接下来我们具体分析一下代码中的一些核心步骤,请大家留意上述代码中注释的编号顺序

    流程分析

    ​ 大概熟悉了这个方法所起的作用之后,我们具体分析一下一些核心步骤所做的事情,按照上述代码中注释的编号顺序,继续往下看:

    1. 提取对应的 beanName

      transformedBeanName(name)方法主要是确定原始名称,将别名解析为规范名称。比如将factorybean类型的beanname的前缀&替换掉。

    2. 缓存中获取单例bean

      跟踪 getSingleton(beanName) 方法我们来到 DefaultSingletonBeanRegistry类中,代码如下:

      protected Object getSingleton(String beanName, boolean allowEarlyReference) {
      		Object singletonObject = this.singletonObjects.get(beanName);
      		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      			synchronized (this.singletonObjects) {
      				// 当某些方法需要提前初始化的时候则会调用 addSingletonFactory  方法将对应的
      				//ObjectFactory 初始化策略存储在 singletonFactories
      				singletonObject = this.earlySingletonObjects.get(beanName);
      				if (singletonObject == null && allowEarlyReference) {
      					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
      					if (singletonFactory != null) {
      						//调用预先设定的 get Object 方法 singletonObject = singletonFactory.getObject();
      						singletonObject = singletonFactory.getObject();
      						//记录在缓存中,earlySingletonObjects 和 singletonFactories 互斥
      						this.earlySingletonObjects.put(beanName, singletonObject);
      						this.singletonFactories.remove(beanName);
      					}
      				}
      			}
      		}
      		return singletonObject;
      	}
      

      ​ 从方法名就可以知道这是获取单例的bean,单例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然 这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试尝试从singletonFactories中加载。 因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖, Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到 缓存中,一旦下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory

      ​ 这个方法首先尝试从singletonObjects里面获取实例,如果获取不到再从earlySingletonObjects 里面获取,如果还获取不到,再尝试从singletonFactories里面获取beanName对应的 ObjectFactory,然后调用这个 ObjectFactory 的 getObject 来创建 bean,并放到 earlySingletonObjects 里面去,并且从singletonFacotories里面remove掉这个ObjectFactory,而对于后续的所 有内存操作都只为了循环依赖检测时候使用,也就是在allowEarlyReference为true的情况下才 会使用,而它默认就是true。
      这里涉及用于存储bean的不同的map简单解释如下。

      • singletonObjects:用于保存 BeanName 和创建 bean 实例之间的关系,bean name —> beaninstance
      • singletonFactories:用于保存BeanName和创建bean的工厂之间的关系,bean name ~> ObjectFactory
      • earlySingletonObjects:也是保存BeanName和创建bean实例之间的关系,与 singletonObjects的不同之处在于,当一个单例bean被放到这里面后,那么当bean还 在创建过程中,就可以通过getBean方法获取到了,其目的是用来检测循环引用。
      • registeredSingletons:用来保存当前所有已注册的bean。
    3. 从bean的实例中获取对象

      ​ 跟踪 getObjectForBeanInstance()方法,我们来到 AbstractBeanFactory类中,代码如下:

      protected Object getObjectForBeanInstance(
      			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
      		// bean name是不是以 & 开头
      		if (BeanFactoryUtils.isFactoryDereference(name)) {
      			if (beanInstance instanceof NullBean) {
      				return beanInstance;
      			}
      			if (!(beanInstance instanceof FactoryBean)) {
      				throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
      			}
      		}
      		// 现在我们有了个 bean 的实例,这个实例可能会是正常的 bean 或者是 FactoryBean
      		// 如果是 FactoryBean 我们使用它创建实例,但是如果用户想要直接获取工厂实例而不是工厂的
      		// getObject 方法对应的实例那么传入的 name 应该加入前缀
      		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
      			return beanInstance;
      		}
      
      		Object object = null;
      		if (mbd == null) {
      			// 尝试从缓存中加载 bean
      			object = getCachedObjectForFactoryBean(beanName);
      		}
      		if (object == null) {
      			// Return bean instance from factory.
      			// 到这里已经明确知道 beaninstance 一定是 FactoryBean 类型
      			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
      			// Caches object obtained from FactoryBean if it is a singleton.
      			//containsBeanDefinition 检测 beanDefinitionMap 中也就是在所有已经加载的类中检测 是否定义 beanName
      			if (mbd == null && containsBeanDefinition(beanName)) {
      				//将存储 XML 配置文件的 GernericBeanDefinition 转换为 RootBeanDefinition,如果指定 BeanName 是子 Bean 的话同时会合并父类的相关属性
      				mbd = getMergedLocalBeanDefinition(beanName);
      			}
      			//是否是用户定义的而不是应用程序本身定义的
      			boolean synthetic = (mbd != null && mbd.isSynthetic());
      			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
      		}
      		return object;
      	}
      

      这个方法中主要确定了bean的类型是不是 FactoryBean 如果是,又委托给 getObjectFromFactoryBean(factory, beanName, !synthetic)方法,继续深入。进入 FactoryBeanRegistrySupport类中:

      protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
      		if (factory.isSingleton() && containsSingleton(beanName)) {
      			synchronized (getSingletonMutex()) {
      				Object object = this.factoryBeanObjectCache.get(beanName);
      				if (object == null) {
      					// 划重点
      					object = doGetObjectFromFactoryBean(factory, beanName);
      					// Only post-process and store if not put there already during getObject() call above
      					// (e.g. because of circular reference processing triggered by custom getBean calls)
      					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
      					if (alreadyThere != null) {
      						object = alreadyThere;
      					} else {
      						if (shouldPostProcess) {
      							if (isSingletonCurrentlyInCreation(beanName)) {
      								// Temporarily return non-post-processed object, not storing it yet..
      								return object;
      							}
      							// 正在创建的bean放到缓存中
      							beforeSingletonCreation(beanName);
      							try {
      								//Spring获取bean的规则中有这样一条 :尽可能保证所有 bean 初始化后都会调用注册的 的 BeanPostProcessor的 postProcessAfterlnitialization  方法进行处理
      								object = postProcessObjectFromFactoryBean(object, beanName);
      							} catch (Throwable ex) {
      								throw new BeanCreationException(beanName,
      										"Post-processing of FactoryBean's singleton object failed", ex);
      							} finally {
      								//正在创建的bean从缓存中移除
      								afterSingletonCreation(beanName);
      							}
      						}
      						if (containsSingleton(beanName)) {
      							this.factoryBeanObjectCache.put(beanName, object);
      						}
      					}
      				}
      				return object;
      			}
      		} else {
      			Object object = doGetObjectFromFactoryBean(factory, beanName);
      			if (shouldPostProcess) {
      				try {
      					object = postProcessObjectFromFactoryBean(object, beanName);
      				} catch (Throwable ex) {
      					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
      				}
      			}
      			return object;
      		}
      	}
      

      在这个方法中我们还没有看到想看的代码不过没关系,细心的你早已发现这里面包含两个重要的方法;Object object = doGetObjectFromFactoryBean(factory, beanName);以及 object = postProcessObjectFromFactoryBean(object, beanName);第一个很明显就是委托获取bean的实现,第二个是bean的后置处理器;后续章节重点分析。

      private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
      			throws BeanCreationException {
      		Object object;
      		try {
      			if (System.getSecurityManager() != null) {
      				AccessControlContext acc = getAccessControlContext();
      				try {
      					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
      				} catch (PrivilegedActionException pae) {
      					throw pae.getException();
      				}
      			} else {
                      // 划重点
      				object = factory.getObject();
      			}
      		} catch (FactoryBeanNotInitializedException ex) {
      			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
      		} catch (Throwable ex) {
      			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
      		}
      		......省略
      		}
      		return object;
      	}
      

      终于我们看到了,object = factory.getObject(); 经过一番波折我们知道了factoryBean的bean最终的获取的对象就是调用它本身的 getObject()实现的。

    4. Definition的转换

      	//将存储 XML 配置文件的 GernericBeanDefinition 转换为 RootBeanDefinition
      				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
      ---------------------------
      protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
      		// Quick check on the concurrent map first, with minimal locking.
      		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
      		if (mbd != null) {
      			return mbd;
      		}
      		// beanDefinitionMap 中获取 beandefination 返回 RootBeanDefinition
      		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
      	}
      --------------------------
      public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
          // 重点
      		BeanDefinition bd = this.beanDefinitionMap.get(beanName);
      		if (bd == null) {
      			if (this.logger.isTraceEnabled()) {
      				this.logger.trace("No bean named '" + beanName + "' found in " + this);
      			}
      			throw new NoSuchBeanDefinitionException(beanName);
      		}
      		return bd;
      	}
      
      

      ​ 在这部分代码中主要是将GernericBeanDefinition 转换为 RootBeanDefinition;在第二节解析xml装配BeanDefinition的时候我们就知道了最初的bean就是GernericBeanDefinition 类型的。而 beanDefinitionMap中的BeanDefinition也是在第二节所说到的,解析好的BeanDefinition所注册的map对象;这也正好前后一一印证了。

    5. 实例化依赖的 bean

      // 单例模式的创建
      sharedInstance = getSingleton(beanName, () -> {
          try {
              // 创建bean
              return createBean(beanName, mbd, args);
          } catch (BeansException ex) {
              destroySingleton(beanName);
              throw ex;
          }
      });
      

      ​ 之前我们讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例bean 就需要从头开始bean的加载过程了,而Spring中使用getSingleton的重载方法实现bean的加 载过程,进一步深入 DefaultSingletonBeanRegistry类中:

      public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
      		Assert.notNull(beanName, "Bean name must not be null");
      		synchronized (this.singletonObjects) {
      			//首先检査对应的 bean 是否已经加载过,因为 singleton 模式其实就是复用以创建的 bean,
      			Object singletonObject = this.singletonObjects.get(beanName);
      			//如果为空.则锁定全局变量并进行处理
      			if (singletonObject == null) {
      				if (this.singletonsCurrentlyInDestruction) {
      					throw new BeanCreationNotAllowedException(beanName,
      							"......");
      				}
      				if (logger.isDebugEnabled()) {
      					logger.debug("......");
      				}
      				// 正在创建的bean 放到缓存中
      				beforeSingletonCreation(beanName);
      				boolean newSingleton = false;
      				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
      				if (recordSuppressedExceptions) {
      					this.suppressedExceptions = new LinkedHashSet<>();
      				}
      				try {
      					singletonObject = singletonFactory.getObject();
      					newSingleton = true;
      				}
      				catch (IllegalStateException ex) {
      					singletonObject = this.singletonObjects.get(beanName);
      					if (singletonObject == null) {
      						throw ex;
      					}
      				}
      				catch (BeanCreationException ex) {
      					if (recordSuppressedExceptions) {
      						for (Exception suppressedException : this.suppressedExceptions) {
      							ex.addRelatedCause(suppressedException);
      						}
      					}
      					throw ex;
      				}
      				finally {
      					if (recordSuppressedExceptions) {
      						this.suppressedExceptions = null;
      					}
      					// 正在创建的bean从缓存中移除
      					afterSingletonCreation(beanName);
      				}
      				if (newSingleton) {
      					// 将结果记录至缓存并删除加载 bean  过程中所记录的各种辅助状态
      					addSingleton(beanName, singletonObject);
      				}
      			}
      			return singletonObject;
      		}
      	}
      

      ​ 上述代码中其实是使用了回调方法,使得程序可以在单例创建的前后做一些准备及处理操 作,而真正的获取单例bean的方法其实并不是在此方法中实现的,其实现逻辑是在ObectFactoty 类型的实例singletonFactory中实现的,我们也能在代码中看到返回的对象也正是调用 singletonFactory.getObject()返回的。而这些准备及处理操作包括如下内容。

      • 检查缓存是否已经加载过。
      • 若没有加载,则记录beanName的正在加载状态。
      • 加载单例前记录加载状态。

      我们返回去看一下 singletonFactory对象的创建过程createBean(beanName, mbd, args),进入 AbstractAutowireCapableBeanFactory类,代码如下:

      protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      			throws BeanCreationException {
      		if (logger.isDebugEnabled()) {
      			logger.debug("......");
      		}
      		RootBeanDefinition mbdToUse = mbd;
      		/**
      		 * 确保此时确实解析了bean类,如果动态解析的类无法存储在共享的合并bean定义中。
      		 */
      which cannot be stored in the shared merged bean definition.
      		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
      		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      			mbdToUse = new RootBeanDefinition(mbd);
      			mbdToUse.setBeanClass(resolvedClass);
      		}
      		// Prepare method overrides.准备方法替代 对override属性进行标记及验证
      		try {
      			mbdToUse.prepareMethodOverrides();
      		} catch (BeanDefinitionValidationException ex) {
      			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
      					beanName, "Validation of method overrides failed", ex);
      		}
      		try {
      			// 给BeanPostProcessors一个返回代理而不是目标bean实例的机会
      			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      			if (bean != null) {
      				return bean;
      			}
      		} catch (Throwable ex) {
      			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);
      		}
      		try {
      			// 开始创建bean
      			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      			if (logger.isDebugEnabled()) {
      				logger.debug("Finished creating instance of bean '" + beanName + "'");
      			}
      			return beanInstance;
      		} catch (...) {
                  ......
      			}
      	}
      

      从代码中我们可以总结出函数完成的具体步骤及功能。

      • 根据设置的class属性或者根据className来解析Class。
      • 对override属性进行标记及验证。
      • 应用初始化前的后处理器,解析指定bean是否存在初始化前的短路操作。

    ​ 创建bean的过程又委托给 doCreateBean(beanName, mbdToUse, args);去实现,那么接下来我们老规矩,继续深入 AbstractAutowireCapableBeanFactory类中:

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    			throws BeanCreationException {
    		// Instantiate the bean.
    		BeanWrapper instanceWrapper = null;
    		if (mbd.isSingleton()) {
    			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    		}
    		if (instanceWrapper == null) {
    			//根据指定 bean 使用对应的策略创建新的实例,如:工厂方法、构造函数自动注入、简单初始化 instancewrapper
    			instanceWrapper = createBeanInstance(beanName, mbd, args);
    		}
    		final Object bean = instanceWrapper.getWrappedInstance();
    		Class<?> beanType = instanceWrapper.getWrappedClass();
    		if (beanType != NullBean.class) {
    			mbd.resolvedTargetType = beanType;
    		}
    		synchronized (mbd.postProcessingLock) {
    			if (!mbd.postProcessed) {
    				try {
                        // bean的后置处理器
    					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    				} catch (Throwable ex) {
    					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    							"......", ex);
    				}
    				mbd.postProcessed = true;
    			}
    		}
    		// 是否需要提早曝光: 单例& 允许循环依赖& 当前 bean
    		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    				isSingletonCurrentlyInCreation(beanName));
    		if (earlySingletonExposure) {
    			if (logger.isDebugEnabled()) {
    				logger.debug("Eagerly caching bean '" + beanName +
    						"' to allow for resolving potential circular references");
    			}
    			// 为避免后期循环依赖,可以在 bean 初始化完成前将创建实例的 Object Factory 加入工厂
    			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    		}
    		// Initialize the bean instance.
    		Object exposedObject = bean;
    		try {
    			// 对 bean 进行填充 , 将各个属性值注入其中,他可能存在依赖于其他bean的属性 ,则会递归初始
    			populateBean(beanName, mbd, instanceWrapper);
    			// 调用初始化方法,比如 init-method
    			exposedObject = initializeBean(beanName, exposedObject, mbd);
    		} catch (Throwable ex) {
    			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
    				throw (BeanCreationException) ex;
    			} else {
    				throw new BeanCreationException(
    						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
    			}
    		}
    
    		if (earlySingletonExposure) {
    			Object earlySingletonReference = getSingleton(beanName, false);
    			// earlySingletonReference只有在检测到有循环依赖的情况下才会不为空
    			if (earlySingletonReference != null) {
    				// 如果 exposedObject  没有在初始化方法中被改变,也就是没有被增强
    				if (exposedObject == bean) {
    					exposedObject = earlySingletonReference;
    				} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
    					String[] dependentBeans = getDependentBeans(beanName);
    					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
    					for (String dependentBean : dependentBeans) {
    						// 检测依赖
    						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
    							actualDependentBeans.add(dependentBean);
    						}
    					}
    					/**
    					 * 因为 bean 创建后其所依赖的 bean —定是已经创建的,
    					 * actualDependentBeans 不为空则表示当前前 bean 创建后其依赖的的 bean 却没有没全部创建完,也就是说存在循环依赖
    					 */
    					if (!actualDependentBeans.isEmpty()) {
    						throw new BeanCurrentlyInCreationException(beanName,
    								"Bean with name '" + beanName + "' has been injected into other beans [" +					StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
    										".......");
    					}
    				}
    			}
    		}
    		// Register bean as disposable.
    		try {
    			// 根据 scopse 注册 bean
    			registerDisposableBeanIfNecessary(beanName, bean, mbd);
    		} catch (BeanDefinitionValidationException ex) {
    			throw ......;
    		}
    		return exposedObject;
    	}
    

    我们来看一下这个方法的整体思路:

    • 如果是单例则需要首先清除缓存。
    • 实例化 bean,将 BeanDefinition 转换为 Bean Wrapper。转换是一个复杂的过程,但是我们可以尝试概括大致的功能,如下所示。
      • 如果存在工厂方法则使用工厂方法进行初始化。
      • 一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造 函数并进行初始化。
      • 如果既不存在工厂方法也不存在带有参数的构造函数,则使用默认的构造函数进行 bean的实例化。
    • MergedBeanDefinitionPostProcessor 的应用。
      bean合并后的处理,Autowired注解正是通过此方法实现诸如类型的预解析。
    • 依赖处理。
      在Spring中会有循环依赖的情况,例如,当A中含有B的属性,而B中又含有A的属性 时就会构成一个循环依赖,此时如果A和B都是单例,那么在Spring中的处理方式就是当创 建B的时候,涉及自动注入A的步骤时,并不是直接去再次创建A,而是通过放入缓存中的 ObjectFactory来创建实例,这样就解决了循环依赖的问题
    • 属性填充。将所有属性填充至bean的实例中。
    • 循环依赖检査。
      之前有提到过,在Sping中解决循环依赖只对单例有效,而对于prototype的bean, Spring 没有好的解决办法,唯一要做的就是抛出异常。在这个步骤里面会检测已经加载的bean是否 已经出现了依赖循环,并判断是否需要抛出异常。
    • 注册 DisposableBeano
      如果配置了 destroy-method,这里需要注册以便于在销毁时候调用。
    • 完成创建并返回。
      可以看到上面的步骤非常的繁琐,每一步骤都使用了大量的代码来完成其功能,最复杂 也是最难以理解的当属循环依赖的处理,在真正进入doCreateBean前我们有必要先了解下循 环依赖。

    6.创建bean的实例
    首先我们从 createBeanlnstance 开始:

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    		// Make sure bean class is actually resolved at this point.
    		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<?> 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) {
    				if (mbd.resolvedConstructorOrFactoryMethod != null) {
    					resolved = true;
    					autowireNecessary = mbd.constructorArgumentsResolved;
    				}
    			}
    		}
    		if (resolved) {
    			if (autowireNecessary) {
    				// 构造函数
    				return autowireConstructor(beanName, mbd, null, null);
    			} else {
    				// 默认的构造函数
    				return instantiateBean(beanName, mbd);
    			}
    		}
    		// 根据参数解析构造函数
    		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    		if (ctors != null ||
    				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
    				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
    			// 构造函数自动驻入
    			return autowireConstructor(beanName, mbd, ctors, args);
    		}
    		// 根据不同的实例化策略进行实例化
    		return instantiateBean(beanName, mbd);
    	}
    

    虽然代码中实例化的细节非常复杂,但是在createBeanlntance方法中我们还是可以清晰地 看到实例化的逻辑的。

    • 如果在RootBeanDefinition中存在factoryMethodName属性,或者说在配置文件中配置 了 factory-method,那么 Spring 会尝试使用 instantiateUsingFactoiyMethod(beanName, mbd, aigs)方法
    • 解析构造函数并进行构造函数的实例化。因为一个bean对应的类中可能会有多个构造 函数,而每个构造函数的参数不同,Spring在根据参数及类型去判断最终会使用哪个构造函数 进行实例化。但是,判断的过程是个比较消耗性能的步骤,所以釆用缓存机制,如果已经解析过则 不需要重复解析而是直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存 的值去取,否则需要再次解析,并将解析的结果添加至RootBeanDefinition中的属性 resolvedConstructorOrFactoryMethod 中。

    我们发现创建 BeanWrapper的任务又委托给 instantiateBean(beanName, mbd);来处理,老规矩继续深入 AbstractAutowireCapableBeanFactory类中:

    	protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    		try {
    			Object beanInstance;
    			final BeanFactory parent = this;
    			if (System.getSecurityManager() != null) {
    				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
    								getInstantiationStrategy().instantiate(mbd, beanName, parent),
    						getAccessControlContext());
    			} else {
    				 // 获取实例化策略
    				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
    			}
    			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
    			initBeanWrapper(bw);
    			return bw;
    		} catch (Throwable ex) {
    			throw new BeanCreationException(
    					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    		}
    	}
    

    依然没有看到我们想看到的类容,继续深入 SimpleInstantiationStrategy类中:

    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    		// Don't override the class with CGLIB if no overrides.
    		// 如果有需要覆盖或者动态替换的方法则当然需要使用 cglib 进行动态代理,因为可以在创建代理的同时将动态方法织入类中
    		// 但是如果没有需要动态改变得方法,为了方便直接反射就可以了
    		if (!bd.hasMethodOverrides()) {
    			Constructor<?> constructorToUse;
    			synchronized (bd.constructorArgumentLock) {
    				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
    				if (constructorToUse == null) {
    					final Class<?> clazz = bd.getBeanClass();
    					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();
    						}
    						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
    					}
    					catch (Throwable ex) {
    						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
    					}
    				}
    			}
    			return BeanUtils.instantiateClass(constructorToUse);
    		}
    		else {
    			// Must generate CGLIB subclass. 必须生成CGLIB子类。
    			return instantiateWithMethodInjection(bd, beanName, owner);
    		}
    	}
    

    ​ 程序中,首先判断如果beanDefinitioikgetMethodOverrides为空也就是 用户没有使用replace或者lookup的配置方法,那么直接使用反射的方式,简单快捷,但是如果使 用了这两个特性,在直接使用反射的方式创建实例就不妥了,因为需要将这两个配置提供的功能切进去,所以就必须要使用动态代理的方式将包含两个特性所对应的逻辑的拦截增强器设置进去, 这样才可以保证在调用方法的时候会被相应的拦截器增强,返回值为包含拦截器的代理实例。至此一个完整的 BeanWrapper就转配完了;接下来返回 AbstractAutowireCapableBeanFactory类的 doCreateBean()方法中,继续完成下面的类容:

    // Initialize the bean instance.
    		Object exposedObject = bean;
    		try {
    			// 对 bean 进行填充 , 将各个属性值注入其中,他可能存在依赖于其他bean的属性 ,则会递归初始
    			populateBean(beanName, mbd, instanceWrapper);
    			// 调用初始化方法,比如 init-method
    			exposedObject = initializeBean(beanName, exposedObject, mbd);
    		} catch (Throwable ex) {
    			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
    				throw (BeanCreationException) ex;
    			} else {
    				throw new BeanCreationException(
    						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
    			}
    		}
    

    populateBean(beanName, mbd, instanceWrapper);完成了对属性的填充,二而initializeBean(beanName, exposedObject, mbd);的作用就显而易见了:

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    		if (System.getSecurityManager() != null) {
    			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    				invokeAwareMethods(beanName, bean);
    				return null;
    			}, getAccessControlContext());
    		} else {
    			// bean是否有aware接口的实现
    			invokeAwareMethods(beanName, bean);
    		}
    		Object wrappedBean = bean;
    		if (mbd == null || !mbd.isSynthetic()) {
    			// 调前置处理器
    			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    		}
    		try {
    			// 执行init方法  自定义的 bean 实 实 现 现 InitializingBean 口 接口
    			invokeInitMethods(beanName, wrappedBean, mbd);
    		} catch (Throwable ex) {
    			throw new BeanCreationException(
    					(mbd != null ? mbd.getResourceDescription() : null),
    					beanName, "Invocation of init method failed", ex);
    		}
    		if (mbd == null || !mbd.isSynthetic()) {
    			// 调后置处理器
    			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    		}
    		return wrappedBean;
    }
    

    虽然说此函数的主要目的是进行客户设定的初始化方法的调用,但是除此之外还有些其他 必要的工作。

    1. 激活Aware方法
      在分析其 前,我们先了解一下Aware的邮 Spring中些Aware相趣口,比如
      BeanFactoryAware、ApplicationContextAware、ResourceLoaderAware x ServletContextAware 等,实 些Aware接口的bean在被初始之后,可以取得一些相对应的资源,例如实现BeanFactoryAware的bean 在初始后,Spring容器将会注入BeanFactory的实例,而实现ApplicationContextAware的bean,在 bean被初始后,将会被注入Applicationcontext的实例等。
    2. 处理器的应用
      BeanPostProcessor相信大家都不陌生,这是Spring中开放式架构中一个必不可少的亮点, 给用户充足的权限去更改或者扩展Spring,而除了 BeanPostProcessor外还有很多其他的 PostProcessor,当然大部分都是以此为基础,继承自 BeanPostProcessor。BeanPostProcessor 的 使用位置就是这里,在调用客户自定义初始化方法前以及调用自定义初始化方法后分别会调用 BeanPostProcessor 的 postProcessBefbrelnitialization 和 postProcessAfterlnitialization 方法,使用 户可以根据自己的业务需求进行响应的处理。
    3. 激活自定义的init方法
      客户定制的初始化方法除了我们熟知的使用配置init-method夕卜,还有使自定义的bean实 现InitializingBean接口 ,并在afterPropertiesSet中实现自己的初始化业务逻辑。

    至此createBean(beanName, mbd, args);方法中的所有核心步骤都完了。回到AbstractBeanFactory中我们发现同开始我们曾分析的方法一样又调用一次·bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);不再阐述。最后一个完整的bean已经初始华完毕了。

    后语

    Spring的加载bean的流程是复杂而又庞大的,我们的分析相对简陋但是也包含了几乎所有的核心流程,日积月累中将会有收获。下一章节我们将继续分析spring容器的功能扩展

    展开全文
  • Springbean加载流程

    2022-06-25 16:42:47
    springbean记载流程

    IOC容器就像是一个工厂,里面有很多流水线生产出一个个产品(bean)。bean的加载流程大概分为:

    • 容器启动阶段
    • bean加载阶段

    容器启动阶段:

    1.配置元信息
    当你生产物品的时候总得知道产品得规格型号信息,元信息就是这个意思。来源于XML文件,注解等。

    2.BeanDefination:
    相当于java中得pojo,当元信息被加载到内存以后就是以BeanDefination的形式存在。

    3、BeanDefinationReader:如果我们要读取xml配置元信息,那么可以使用XmlBeanDefinationReader。如果我们要读取properties配置文件,那么可以使用PropertiesBeanDefinitionReader加载。而如果我们要读取注解配置元信息,那么可以使用 AnnotatedBeanDefinitionReader加载。我们也可以很方便的自定义BeanDefinationReader来自己控制配置元信息的加载。总的来说,BeanDefinationReader的作用就是加载配置元信息,并将其转化为内存形式的BeanDefination,并存在BeanDefinationRegistry中。通过键值对的方式,键是通过特定的bean定义的id,映射到相应的BeanDefination。

    4、BeanDefinationRegistry:

    执行到这里,Spring已经将存在于各处的配置元信息加载到内存,并转化为BeanDefination的形式,这样我们需要创建某一个对象实例的时候,找到相应的BeanDefination然后创建对象即可。那么我们需要某一个对象的时候,去哪里找到对应的BeanDefination呢?这种通过Bean定义的id找到对象的BeanDefination的对应关系或者说映射关系又是如何保存的呢?这就引出了BeanDefinationRegistry了。

    Spring通过BeanDefinationReader将配置元信息加载到内存生成相应的BeanDefination之后,就将其注册到BeanDefinationRegistry中,BeanDefinationRegistry就是一个存放BeanDefination的大篮子,它也是一种键值对的形式,通过特定的Bean定义的id,映射到相应的BeanDefination。

    5、BeanFactoryPostProcessor:

    BeanFactoryPostProcessor是容器启动阶段Spring提供的一个扩展点,主要负责对注册到BeanDefinationRegistry中的一个个的BeanDefination进行一定程度上的修改与替换。例如我们的配置元信息中有些可能会修改的配置信息散落到各处,不够灵活,修改相应配置的时候比较麻烦,这时我们可以使用占位符的方式来配置。例如配置Jdbc的DataSource连接的时候可以这样配置:

    <bean id="dataSource"  
        class="org.apache.commons.dbcp.BasicDataSource"  
        destroy-method="close">  
        <property name="maxIdle" value="${jdbc.maxIdle}"></property>  
        <property name="maxActive" value="${jdbc.maxActive}"></property>  
        <property name="maxWait" value="${jdbc.maxWait}"></property>  
        <property name="minIdle" value="${jdbc.minIdle}"></property>  
      
        <property name="driverClassName"  
            value="${jdbc.driverClassName}">  
        </property>  
        <property name="url" value="${jdbc.url}"></property>  
      
        <property name="username" value="${jdbc.username}"></property>  
        <property name="password" value="${jdbc.password}"></property>  
    </bean> 
    

    BeanFactoryPostProcessor就会对注册到BeanDefinationRegistry中的BeanDefination做最后的修改,替换$占位符为配置文件中的真实的数据。
    在这里插入图片描述

    二、Bean的获取阶段
    在容器的启动阶段就完成了bean的注册,以BeanDefination储存在BeanDefinationRegister中,如果不是选择懒加载(BeanFactory是懒加载)的话,在容器启动完成后执行finishBeanFactoryInitialization()方法,隐式的调用所有对象的getBean()方法实例化所有配置的Bean,完成类的加载。
    1.doGetBean():bean的获取
    doGetBean的方法就是创建Bean之前,先去缓存中或BeanFactory工厂中查看是否存在bean,如果存在,则返回,不存在则进行相应的创建流程。

    1. 检查是不是别名,需要进行解析转换
    2. 尝试从缓存中加载实例,如果获取直接返回,在缓存中获取的bean是原始bean还需要进行实例化,如合并RootBeandefination、BeanPostProcessor进行实例前置处理,实例化,实例后置处理。
    3. 如果缓存中没有对应的bean,则先进行依赖循环检查,存在则报错,如果缓存中没有数据,就会转到父类加工厂(有点像双亲委任制),如果当前的xml文件不报换beanname所对应的配置,就只能到父类工厂中尝试加载
    4. 存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,即为合并父类定义。
    5. 初始化依赖的bean,即进行被依赖bean的实例化初始化流程。
    6. 创建bean,默认是单例
    protected <T> T doGetBean(
    			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
    			throws BeansException {
     
            /*
            1、转换beanName(别名转换):传入的参数name可能只是别名,也可能是FactoryBean,所以需要进行解析转换:
            (1)消除修饰符,比如工厂引用前缀 String FACTORY_BEAN_PREFIX = "&";
            (2)解决spring中alias标签的别名问题
            */ 
    		final String beanName = transformedBeanName(name);
    		Object bean;
     
            //2、尝试从缓存中去加载实例,如果获取到了就直接返回
    		// Eagerly check singleton cache for manually registered singletons.
    		Object sharedInstance = getSingleton(beanName);
    		//如果缓存中存在对应的bean
    		if (sharedInstance != null && args == null) {
    			if (logger.isDebugEnabled()) {
    				if (isSingletonCurrentlyInCreation(beanName)) {
    					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
    							"' that is not fully initialized yet - a consequence of a circular reference");
    				}
    				else {
    					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
    				}
    			}
    			
    			//3、缓存渠道的bean的实例化。从缓存中获取的bean是原始状态的bean,需要在这里对bean进行bean实例化。
    			// 此时会进行 合并RootBeanDefinition、BeanPostProcessor进行实例前置处理、实例化、实例后置处理。
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    		}
            // 如果缓存中没有对应bean
    		else { 
    		    //4、循环依赖检查。 (构造器的循环依赖)循环依赖存在,则报错。
    			// Fail if we're already creating this bean instance:
    			// We're assumably within a circular reference.
    			if (isPrototypeCurrentlyInCreation(beanName)) {
    				throw new BeanCurrentlyInCreationException(beanName);
    			}
     
                // 5、如果缓存中没有数据,就会转到父类工厂去加载
                //获取父工厂
    			// Check if bean definition exists in this factory.
    			BeanFactory parentBeanFactory = getParentBeanFactory();
    			
                //!containsBeanDefinition(beanName)就是检测如果当前加载的xml配置文件中不包含beanName所对应的配置,就只能到parentBeanFacotory去尝试加载bean。
    			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    				// Not found -> check parent.
    				String nameToLookup = originalBeanName(name);
    				if (args != null) {
    					// Delegation to parent with explicit args.
    					return (T) parentBeanFactory.getBean(nameToLookup, args);
    				}
    				else {
    					// No args -> delegate to standard getBean method.
    					return parentBeanFactory.getBean(nameToLookup, requiredType);
    				}
    			}
     
    			if (!typeCheckOnly) {
    				markBeanAsCreated(beanName);
    			}
     
                //6、存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,即为合并父类定义。
    			try {
                    // XML配置文件中读取到的bean信息是存储在GernericBeanDefinition中的,但Bean的后续处理是针对于RootBeanDefinition的,所以需要转换后才能进行后续操作。
    				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    				checkMergedBeanDefinition(mbd, beanName, args);
     
    				// Guarantee initialization of beans that the current bean depends on.
    				//7、初始化依赖的bean
    				String[] dependsOn = mbd.getDependsOn();
    				//bean中可能依赖了其他bean属性,在初始化bean之前会先初始化这个bean所依赖的bean属性。
    				if (dependsOn != null) {
    					for (String dependsOnBean : dependsOn) {
    						if (isDependent(beanName, dependsOnBean)) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
    						}
    						registerDependentBean(dependsOnBean, beanName);
    						getBean(dependsOnBean);
    					}
    				}
     
                    //8、创建bean
    				// Create bean instance.
    				if (mbd.isSingleton()) {
    					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
    						@Override
    						public Object getObject() throws BeansException {
    							try {
    								return createBean(beanName, mbd, args);
    							}
    							catch (BeansException ex) {
    								// Explicitly remove instance from singleton cache: It might have been put there
    								// eagerly by the creation process, to allow for circular reference resolution.
    								// Also remove any beans that received a temporary reference to the bean.
    								destroySingleton(beanName);
    								throw ex;
    							}
    						}
    					});
    					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    				}
     
    				else if (mbd.isPrototype()) {
    					// It's a prototype -> create a new instance.
    					Object prototypeInstance = null;
    					try {
    						beforePrototypeCreation(beanName);
    						prototypeInstance = createBean(beanName, mbd, args);
    					}
    					finally {
    						afterPrototypeCreation(beanName);
    					}
    					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    				}
     
    				else {
    					String scopeName = mbd.getScope();
    					final Scope scope = this.scopes.get(scopeName);
    					if (scope == null) {
    						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
    					}
    					try {
    						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
    							@Override
    							public Object getObject() throws BeansException {
    								beforePrototypeCreation(beanName);
    								try {
    									return createBean(beanName, mbd, args);
    								}
    								finally {
    									afterPrototypeCreation(beanName);
    								}
    							}
    						});
    						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    					}
    					catch (IllegalStateException ex) {
    						throw new BeanCreationException(beanName,
    								"Scope '" + scopeName + "' is not active for the current thread; consider " +
    								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
    								ex);
    					}
    				}
    			}
    			catch (BeansException ex) {
    				cleanupAfterBeanCreationFailure(beanName);
    				throw ex;
    			}
    		}
     
    		// Check if required type matches the type of the actual bean instance.
    		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
    			try {
    				return getTypeConverter().convertIfNecessary(bean, requiredType);
    			}
    			catch (TypeMismatchException ex) {
    				if (logger.isDebugEnabled()) {
    					logger.debug("Failed to convert bean '" + name + "' to required type [" +
    							ClassUtils.getQualifiedName(requiredType) + "]", ex);
    				}
    				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    			}
    		}
    		return (T) bean;
    	}
     
    

    2.在缓存中获取单例bean 调用getSingleton(beanname,allowearlyReference)方法
    1).从一级缓存中获取,若为空,则检查是否在创建中
    2).检查的时候要加锁,防止并发创建
    3).从二级bean中获取bean,如果正在加载,则不处理,否则调用addSingletonFactory 方法将对应的objectFactory 初始化策略存储在 singletonFactories,也就是三级缓存中,三级缓存存储的也是早期bean。在解决循环依赖中,三级缓存是可以对早期的类对象进行自定义处理,将处理完的对象,放在二级缓存中,若还有循环依赖的处理,拿的是二级循环中的对象。

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    	// 从缓存池中获取bean:singletonObjects 一级缓
        Object singletonObject = this.singletonObjects.get(beanName);
    	
        // 如果一级缓存中为null,再判断是否正在创建
    	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    		// 加锁,防止并发创建
    		synchronized (this.singletonObjects) {
    			// 从二级缓存中获取bean,如果此 bean 正在加载则不处理
    			singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
    				// 当某些方法需要提前初始化,调用 addSingletonFactory 方法将对应的objectFactory 初始化策略存储在 singletonFactories
    				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    				if (singletonFactory != null) {
    					singletonObject = singletonFactory.getObject();
    					this.earlySingletonObjects.put(beanName, singletonObject);
    					this.singletonFactories.remove(beanName);
    				}
    			}
    		}
    	}
    	return singletonObject;
    }
    

    Bean实例化阶段执行的顺序
    在这里插入图片描述

    展开全文
  • springbean装载

    千次阅读 2018-10-26 20:45:21
    一:springbean装载方式 springbean装载方式存在三种: 在xml中进行显式配置; 在java中进行显式配置; 隐式的bean发现机制和自动装配; 二:自动化装配bean spring 从两个角度来实现自动化装配: 组件...
  • 通过注解注入Bean背景我们谈到Spring的时候一定会提到IOC容器、DI依赖注入,Spring通过将一个个类标注为Bean的方法注入到IOC容器中,达到了控制反转的效果。那么我们刚开始...
  • SpringBean加载流程

    万次阅读 多人点赞 2021-02-18 02:44:40
    Spring IOC容器就像是一个生产产品的流水线上的机器,Spring创建出来的Bean就好像是流水线的终点生产出来的一个个精美绝伦的产品。既然是机器,总要先启动,Spring也不例外。因此Bean的加载流程总体上来说可以分为两...
  • Spring Bean的加载方式【8种】

    千次阅读 2022-04-18 13:37:38
    本文讲述了Spring bean 的八种加载方式,包含的内容足以应付大多数场景
  • Spring 设计模式总结 ...根据传入一个唯一的标识来获得Bean对象, 但是否是在传入参数后创建 还是传入参数前创建这个要根据具体情况来定。 实质: 由一个工厂类根据传入的参数, 动态决定应该创建哪一个产品类
  • Spring往容器中注入组件四种方式: 1. 包扫描(@ComponentScan+@Controller,@Service,@Component,@Repository) 开发中经常使用。 2. 配置类 @Configuration + @Bean方式 一般用导入第三方的组件 3. 使用@Import...
  • spring--bean加载流程

    千次阅读 2020-04-23 15:15:28
    spring bean的建模对象,普通的class对象无法完成spring bean的抽象,bean的作用域、注入模型、懒加载信息等。所以抽象出BeanDefinition,以便spring实例化一个bean。 class对象描述一个类的属性、方法等信息。 ...
  • SpringBoot装载bean的几种方式

    千次阅读 2018-05-29 21:31:00
    * @Description: @Import用来导入一个或多个普通类(bean会被spring容器托管),或者配置类(配置类中的bean都会被spring容器托管) * @author Liu * @date 2018年6月10日 下午6:21:28 * */ @ComponentScan @Import...
  • Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,如何在程序中获取Spring配置的bean呢?下面通过本文给大家介绍Java中Spring获取bean方法小结,对spring获取bean方法相关知识感兴趣的朋友一起学习...
  • SpringBean配置

    2015-12-08 20:10:56
    Spring IOC和DI概述,Bean的配置形式,IOC容器BeanFactory和ApplicationContext概述,依赖注入的方式,属性注入,构造器注入等案例
  • 使用注解装载Bean的步骤: 目录 一、扫描 二、装载 三、注入 一、扫描 两种方式: a.使用注解 @ComponentScan ApplicationContext ctx = new AnnotationConfigApplicationContext(ApplicationConfi...
  • 主要介绍了Spring Bean装载方式代码实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • spring IOC反射装载bean

    2017-03-04 15:46:39
    spring基于xml配置加载bean 的demo 了解spring的反射机制
  • 主要介绍了Java的Spring框架下bean的自动装载方式,Spring是Java的SSH三大web开发框架之一,需要的朋友可以参考下
  • 同样地,在Spring中,要想使用容器中地Bean对象,也需要实例化Bean。 构造方法实例化 Spring容器通过Bean对应类中默认的无参构造方法来实例化Bean。 下面通过简单程序,来测试Bean1()无参构造方法是否可以实例化...
  • spring加载bean流程解析

    千次阅读 2022-01-10 11:16:34
    spring作为目前我们开发的基础框架,每天的开发工作基本和他形影不离,作为管理bean的最经典、优秀的框架,它的复杂程度往往令人望而却步。不过作为朝夕相处的框架,我们必须得明白一个问题就是spring是如何加载bean的...
  • 本篇文章会继续上篇文章 applicationcontext 体系结构、 beanfactory体系结构、以及 ioc 容器启动 的初始化、设置配置路径、以及 refresh部分大致的一个结构,本篇文章会继续解读 bean定义、 加载过程, 注册部分 ...
  • Spring 注入 Bean 的七种方式

    千次阅读 2021-09-01 00:05:40
    来源:juejin.cn/post/6844903813753602056通过注解注入Bean背景我们谈到Spring的时候一定会提到IOC容器、DI依赖注入,Spring通过将一个个类标...
  • springbean的自动装配(详细)

    千次阅读 2021-08-15 12:46:10
    spring会在应用上下文中为某个bean寻找其依赖的bean。 1.新建两个实体类 public class Address { private String address; // get,set,toString } public class Student { private String name; private ...
  • Spring创建Bean的过程

    2020-08-10 14:12:16
    Spring创建Bean的过程
  • Spring控制Bean加载顺序

    2021-02-26 09:19:33
    spring容器载入bean顺序是不确定的,spring框架没有约定特定顺序逻辑规范。 但spring保证如果A依赖B(如beanA中有@Autowired B的变量),那么B将先于A被加载。但如果beanA不直接依赖B,我们如何让B仍先加载呢? 控制...
  • 先贴spring的开发文档,有助于大家学习http://shouce.jb51.net/spring/beans.html#beans-factory-class一直想研究一下spring bean的控制反转的实现,废话不多说。1、先建了一个WEB工程,导入相关spring的jar包,装载...
  • spring源码深度解析—bean的加载(上) 1. 概述 前面我们已经分析了spring对于xml配置文件的解析,接下来我们将对bean的加载进行探索。bean的加载比配置文件的解析要复杂的多。还记得我们在测试读取配置文件后获取...
  • 1.Spring源码怎么学 注:这里笔者只是分享一下自己的心得,可能并不适合所有人,如果您觉得有道理不妨一试。 刚看Spring源码优先理清楚整体逻辑,切记刚入手就开始扣代码细节,容易越陷越深导致学迷。建议先理...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,313
精华内容 9,725
关键字:

spring装载bean

spring 订阅