6.2.3-Bean的加载处理

AbstractBeanFactory中doGetBean方法中始终调用了getObjectForBeanInstance方法,这个方法是对参数进行过滤;

 

  1     @SuppressWarnings("unchecked")
  2     protected <T> T doGetBean(
  3             final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
  4             throws BeansException {
  5 
  6         final String beanName = transformedBeanName(name);
  7         Object bean;
  8 
  9         // Eagerly check singleton cache for manually registered singletons.
 10         Object sharedInstance = getSingleton(beanName);
 11         if (sharedInstance != null && args == null) {
 12             if (logger.isDebugEnabled()) {
 13                 if (isSingletonCurrentlyInCreation(beanName)) {
 14                     logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
 15                             "' that is not fully initialized yet - a consequence of a circular reference");
 16                 }
 17                 else {
 18                     logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
 19                 }
 20             }
 21             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 22         }
 23 
 24         else {
 25             // Fail if we're already creating this bean instance:
 26             // We're assumably within a circular reference.
 27             if (isPrototypeCurrentlyInCreation(beanName)) {
 28                 throw new BeanCurrentlyInCreationException(beanName);
 29             }
 30 
 31             // Check if bean definition exists in this factory.
 32             BeanFactory parentBeanFactory = getParentBeanFactory();
 33             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 34                 // Not found -> check parent.
 35                 String nameToLookup = originalBeanName(name);
 36                 if (args != null) {
 37                     // Delegation to parent with explicit args.
 38                     return (T) parentBeanFactory.getBean(nameToLookup, args);
 39                 }
 40                 else {
 41                     // No args -> delegate to standard getBean method.
 42                     return parentBeanFactory.getBean(nameToLookup, requiredType);
 43                 }
 44             }
 45 
 46             if (!typeCheckOnly) {
 47                 markBeanAsCreated(beanName);
 48             }
 49 
 50             try {
 51                 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 52                 checkMergedBeanDefinition(mbd, beanName, args);
 53 
 54                 // Guarantee initialization of beans that the current bean depends on.
 55                 String[] dependsOn = mbd.getDependsOn();
 56                 if (dependsOn != null) {
 57                     for (String dependsOnBean : dependsOn) {
 58                         if (isDependent(beanName, dependsOnBean)) {
 59                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 60                                     "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
 61                         }
 62                         registerDependentBean(dependsOnBean, beanName);
 63                         getBean(dependsOnBean);
 64                     }
 65                 }
 66 
 67                 // Create bean instance.
 68                 if (mbd.isSingleton()) {
 69                     sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
 70                         @Override
 71                         public Object getObject() throws BeansException {
 72                             try {
 73                                 return createBean(beanName, mbd, args);
 74                             }
 75                             catch (BeansException ex) {
 76                                 // Explicitly remove instance from singleton cache: It might have been put there
 77                                 // eagerly by the creation process, to allow for circular reference resolution.
 78                                 // Also remove any beans that received a temporary reference to the bean.
 79                                 destroySingleton(beanName);
 80                                 throw ex;
 81                             }
 82                         }
 83                     });
 84                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
 85                 }
 86 
 87                 else if (mbd.isPrototype()) {
 88                     // It's a prototype -> create a new instance.
 89                     Object prototypeInstance = null;
 90                     try {
 91                         beforePrototypeCreation(beanName);
 92                         prototypeInstance = createBean(beanName, mbd, args);
 93                     }
 94                     finally {
 95                         afterPrototypeCreation(beanName);
 96                     }
 97                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
 98                 }
 99 
100                 else {
101                     String scopeName = mbd.getScope();
102                     final Scope scope = this.scopes.get(scopeName);
103                     if (scope == null) {
104                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
105                     }
106                     try {
107                         Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
108                             @Override
109                             public Object getObject() throws BeansException {
110                                 beforePrototypeCreation(beanName);
111                                 try {
112                                     return createBean(beanName, mbd, args);
113                                 }
114                                 finally {
115                                     afterPrototypeCreation(beanName);
116                                 }
117                             }
118                         });
119                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
120                     }
121                     catch (IllegalStateException ex) {
122                         throw new BeanCreationException(beanName,
123                                 "Scope '" + scopeName + "' is not active for the current thread; consider " +
124                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
125                                 ex);
126                     }
127                 }
128             }
129             catch (BeansException ex) {
130                 cleanupAfterBeanCreationFailure(beanName);
131                 throw ex;
132             }
133         }
134 
135         // Check if required type matches the type of the actual bean instance.
136         if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
137             try {
138                 return getTypeConverter().convertIfNecessary(bean, requiredType);
139             }
140             catch (TypeMismatchException ex) {
141                 if (logger.isDebugEnabled()) {
142                     logger.debug("Failed to convert bean '" + name + "' to required type [" +
143                             ClassUtils.getQualifiedName(requiredType) + "]", ex);
144                 }
145                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
146             }
147         }
148         return (T) bean;
149     }
View Code
    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;
    }
View Code

getObjectForBeanInstance方法;

 

getObjectFromFactoryBean;单例时候,确保实例是全局唯一的,主要对缓存的Map进行查询是否已经存在!

 

    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 (object != null && shouldPostProcess) {
                            try {
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                        }
                        this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
                    }
                }
                return (object != NULL_OBJECT ? object : null);
            }
        }
        else {
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (object != null && shouldPostProcess) {
                try {
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
    }

  doGetObjectFromFactoryBean: 实实在在的实例化

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(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public Object run() throws Exception {
                                return 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);
        }

        // Do not accept a null value for a FactoryBean that's not fully
        // initialized yet: Many FactoryBeans just return null then.
        if (object == null && isSingletonCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(
                    beanName, "FactoryBean which is currently in creation returned null from getObject");
        }
        return object;
    }

 

这个方法其实就做了factory.getObject()

 

对以上这几部,

1.首先对doGetBean()方法中参数的过滤 getObjectForBeanInstance

  主要参数:  Object beanInstance, String name, String beanName, RootBeanDefinition mbd

  对name的过滤,如果name制定要获取FactoryBean本身实例,而beanInstance却又不是FactoryBean,直接抛异常

  2.对beanInstance进行过了,判断不属于FactoryBean 或者

if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}

 

对name 进行判断是不是工厂bean,2条有一条就直接返回实例,

 

public static boolean isFactoryDereference(String name) {
return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}

  1. 尝试从缓存中获取实例[FactoryBeanRegistrySupport负责]
  2. 准备beanDefinition,委托getObjectFromFactoryBean处理

单例时保障实例全局唯一,同时也是多例的方法,getObjectFromFactoryBean(factory, beanName, !synthetic);

1.判断是不是单例,

  1.1   先查缓存,不存在就直接调用doGetObjectFromFactoryBean去实例化一个,

  1.2  由于这样新建就没有机会调用BeanPostProcessor了,所以这边直接调用其postProcessAfterInitialization

@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}

  1.3 把生产的实例再换成到map中

  

 

doGetObjectFromFactoryBean

就调用了getobject方法

 

posted @ 2017-05-03 14:49  指针怒草内存栈  阅读(151)  评论(0编辑  收藏  举报