轉自:http://songzi0206.iteye.com/blog/1430239
當 BeanDefinition 注冊完畢以后, Spring Bean 工廠就可以隨時根據需要進行實例化了。對於XmlBeanFactory 來說,實例化默認是延遲進行的,也就是說在 getBean 的時候才會;而對於 ApplicationContext來說,實例化會在容器啟動后通過 AbstractApplicationContext 中 reflash 方法自動進行,主要經過方法鏈:reflesh() à finishBeanFactoryInitialization (factory) à DefaultListableBeanFactory.preInstantiateSingletons (), 在這里會根據注冊的 BeanDefinition 信息依此調用 getBean(beanName) 。而真正實例化的邏輯和 BeanFactory 是“殊途同歸”的,所有有關 Bean 實例化都可以從 getBean(beanName) 入手。
AbstractBeanFactory 有四個 getBean 的重載方法,不管調用哪個方法最終都是會調用另一個 doGetBean 方法:
- public Object getBean(String name) throws BeansException {
- return getBean(name, null, null);
- }
- public Object getBean(String name, Class requiredType) throws BeansException {
- return getBean(name, requiredType, null);
- }
- public Object getBean(String name, Object[] args) throws BeansException {
- return getBean(name, null, args);
- }
- /**
- * Return an instance, which may be shared or independent, of the specified bean.
- * @param name the name of the bean to retrieve
- * @param requiredType the required type of the bean to retrieve
- * @param args arguments to use if creating a prototype using explicit arguments to a
- * static factory method. It is invalid to use a non-null args value in any other case.
- * @return an instance of the bean
- * @throws BeansException if the bean could not be created
- */
- public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {
- return doGetBean(name, requiredType, args, false);
- }
doGetBean方法比較長一點,見下面注釋:
- protected Object doGetBean(
- final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
- throws BeansException {
- //bean name處理,去除FactoryBean前綴等
- final String beanName = transformedBeanName(name);
- Object bean = null;
- //先從singleton緩存中查看是否已經實例化過該Bean,根據是否有緩存分為兩個分支分別處理
- Object sharedInstance = getSingleton(beanName);
- if (sharedInstance != null && args == null) {
- // 分支一,若緩存中獲取到了並且該BeanDefinition信息表明該bean是singleton的,直接將獲取到的緩存Bean
- //(有可能是半成品)交給getObjectForBeanInstance處理
- /*.........省略logger部分代碼............*/
- //調用getObjectForBeanInstance處理
- bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
- }else {
- // 分之二:沒有緩存,則需要從頭實例化該bean
- // We're assumably within a circular reference.
- if (isPrototypeCurrentlyInCreation(beanName)) {
- throw new BeanCurrentlyInCreationException(beanName);}
- // 檢查BeanDefinition是否在當前工廠或父工廠
- BeanFactory parentBeanFactory = getParentBeanFactory();
- if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
- // Not found -> check parent.
- String nameToLookup = originalBeanName(name);
- if (args != null) {
- // 父工廠getBean
- return parentBeanFactory.getBean(nameToLookup, args);
- }
- else {
- // No args -> delegate to standard getBean method.
- return parentBeanFactory.getBean(nameToLookup, requiredType);
- }
- }
- //將bean加入“正在創建”的集合,完成后會remove,對應afterSingletonCreation/afterPrototypeCreation方法
- if (!typeCheckOnly) {
- markBeanAsCreated(beanName);
- }
- final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
- checkMergedBeanDefinition(mbd, beanName, args);
- // 解決依賴關系,將依賴的bean提前實例化
- String[] dependsOn = mbd.getDependsOn();
- if (dependsOn != null) {
- for (int i = 0; i < dependsOn.length; i++) {
- String dependsOnBean = dependsOn[i];
- getBean(dependsOnBean);
- registerDependentBean(dependsOnBean, beanName);
- }
- }
- // 這里又需要根據bean的類型分為三種情況:singleton、prototype、request/session
- if (mbd.isSingleton()) {
- //通過自定義ObjectFactory實例化Bean,此結果可能是半成品(是FactoryBean等)
- sharedInstance = getSingleton(beanName, new ObjectFactory() {
- public Object getObject() throws BeansException {
- try {
- //真正實例化裝配的邏輯在createBean方法中
- 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方法處理
- bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
- }
- else if (mbd.isPrototype()) {
- // It's a prototype -> create a new instance.
- Object prototypeInstance = null;
- try {
- beforePrototypeCreation(beanName);
- //真正實例化裝配的邏輯在createBean方法中
- prototypeInstance = createBean(beanName, mbd, args);
- }
- finally {
- afterPrototypeCreation(beanName);
- }
- //上一步半成品的Bean交給getObjectForBeanInstance方法處理
- bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
- }
- else {
- //request、session 的bean
- String scopeName = mbd.getScope();
- final Scope scope = (Scope) this.scopes.get(scopeName);
- if (scope == null) {
- throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
- }
- try {
- Object scopedInstance = scope.get(beanName, new ObjectFactory() {
- public Object getObject() throws BeansException {
- beforePrototypeCreation(beanName);
- try {
- //真正實例化裝配的邏輯在createBean方法中
- return createBean(beanName, mbd, args);
- }
- finally {
- afterPrototypeCreation(beanName);
- }
- }
- });
- //上一步半成品的Bean交給getObjectForBeanInstance方法處理
- 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);
- }
- }
- }
- // Check if required type matches the type of the actual bean instance.
- if (requiredType != null && bean != null &&
- !requiredType.isAssignableFrom(bean.getClass())) {
- throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
- }
- return bean;
- }
通過注釋,可以整理出較清晰的邏輯: 檢查Bean緩存,已經有緩存的Bean對象(有可能是半成品)則交給getObjectForBeanInstance方法處理;否則先根據Bean的生命周期類型分別實例化,每種情況大致都分兩步,第一步都交給createBean方法生產一個半成品的bean對象,然后同樣是將半成品的bean交給getObjectForBeanInstance方法處理。所以關鍵的邏輯就在這兩個方法了,下面以singleton為例看看這兩個方法,具體代碼:
- sharedInstance = getSingleton(beanName, new ObjectFactory() {
- 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);
getSingleton方法做的工作主要是實例化bean之前和之后回調beforeSingletonCreation/afterSingletonCreation、實例化bean、以及將bean對象緩存起來,具體實例化bean是通過回調匿名對象ObjectFactory的getObject方法實現的,從代碼中明顯看到主要是createBean方法。這里要特別注意下,緩存的bean對象是createBean生產的,這個方法生產的bean只是“半成品”,有可能是個factoryBean,真正返回給客戶端使用的bean還必須進行下一步getObjectBeanInstance處理。所以緩存的bean對象可以認為是“半成品”,這就和前文代碼中的注釋相呼應(緩存中若取到了bean,必須進行getObjectBeanInstance處理)。
對createBean方法實際上在“Spring IOC之BeanFactory”中已經有過分析,所以流程就不再簡單重復,直接按步驟:
1. resolveBeanClass(mbd, beanName);
2. mbd.prepareMethodOverrides();//Spring IOC之BeanFactory已有解釋,不重復
3. Object bean = resolveBeforeInstantiation(beanName, mbd);
解釋下,這里主要對於一些代理的bean做處理,我們平常經常會配置一些AOP模塊,對於需要aop增強的bean實際上都會經過spring代理織入,而這些bean的代理邏輯應該就在這里處理了,具體看看這部分的代碼:
- /**
- * Apply before-instantiation post-processors, resolving whether there is a
- * before-instantiation shortcut for the specified bean.
- * @param beanName the name of the bean
- * @param mbd the bean definition for the bean
- * @return the shortcut-determined bean instance, or <code>null</code> if none
- */
- protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
- Object bean = null;
- if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
- // Make sure bean class is actually resolved at this point.
- if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
- bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);
- if (bean != null) {
- bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
- }
- }
- mbd.beforeInstantiationResolved = Boolean.valueOf(bean != null);
- }
- return bean;
- }
- /**
- * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
- * (by class and name), invoking their <code>postProcessBeforeInstantiation</code> methods.
- * <p>Any returned object will be used as the bean instead of actually instantiating
- * the target bean. A <code>null</code> return value from the post-processor will
- * result in the target bean being instantiated.
- * @param beanClass the class of the bean to be instantiated
- * @param beanName the name of the bean
- * @return the bean object to use instead of a default instance of the target bean, or <code>null</code>
- * @throws BeansException if any post-processing failed
- * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
- */
- protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName)
- throws BeansException {
- for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
- BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
- if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
- InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
- Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
- if (result != null) {
- return result;
- }
- }
- }
- return null;
- }
- //AbstractAutoProxyCreator
- public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
- Object cacheKey = getCacheKey(beanClass, beanName);
- if (!this.targetSourcedBeans.contains(cacheKey)) {
- if (this.advisedBeans.contains(cacheKey) || this.nonAdvisedBeans.contains(cacheKey)) {
- return null;
- }
- if (isInfrastructureClass(beanClass, beanName) || shouldSkip(beanClass, beanName)) {
- this.nonAdvisedBeans.add(cacheKey);
- return null;
- }
- }
- // Create proxy here if we have a custom TargetSource.
- // Suppresses unnecessary default instantiation of the target bean:
- // The TargetSource will handle target instances in a custom fashion.
- TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
- if (targetSource != null) {
- this.targetSourcedBeans.add(beanName);
- Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
- Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
- this.proxyTypes.put(cacheKey, proxy.getClass());
- return proxy;
- }
- return null;
- }
對於AutoProxy部分代碼要放到spring aop部分中去寫了,這里只要明白如果是代理bean在postProcessBeforeInstantiation階段會返回一個proxy,這時候bean已經算是實例化好了,再調用applyBeanPostProcessorsAfterInitialization即BeanPostProcessor.postProcessAfterInitialization回調進行屬性的設置。最后的結果就可以返回bean對象了,只是一個Proxy Bean Object.
4. Object beanInstance = doCreateBean(beanName, mbd, args);//如果是代理bean就不會走到這一步
解釋下:對於非代理的bean,基本上實例化的邏輯就在doCreateBean這個方法了,這個方法在“Spring IOC之BeanFactory”中已經有過分析,所以不重復解釋了,貼一個bean生命周期的流程圖做為createBean方法的結尾:
上圖不是我所畫,來源於spring IOC容器介紹。
半成品出來之后還需要調用getObjectForBeanInstance進一步處理,這個方法:
- protected Object getObjectForBeanInstance(
- Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
- // Don't let calling code try to dereference the factory if the bean isn't a factory.
- if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
- throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
- }
- // Now we have the bean instance, which may be a normal bean or a FactoryBean.
- // If it's a FactoryBean, we use it to create a bean instance, unless the
- // caller actually wants a reference to the factory.
- if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
- return beanInstance;
- }
- Object object = null;
- if (mbd == null) {
- object = getCachedObjectForFactoryBean(beanName);
- }
- if (object == null) {
- // Return bean instance from factory.
- FactoryBean factory = (FactoryBean) beanInstance;
- // Caches object obtained from FactoryBean if it is a singleton.
- if (mbd == null && containsBeanDefinition(beanName)) {
- mbd = getMergedLocalBeanDefinition(beanName);
- }
- boolean synthetic = (mbd != null && mbd.isSynthetic());
- object = getObjectFromFactoryBean(factory, beanName, !synthetic);
- }
- return object;
- }
開始部分是邏輯檢查,是否是FactoryBean,后面是從factoryBean中獲取實際的Bean。獲取bean也是先檢查緩存,沒有緩存再getObjectFromFactoryBean獲取,詳細再doGetObjectFromFactoryBean方法中,最后將獲取的bean緩存起來。代碼就不貼了。