https://blog.csdn.net/qq_30257149/article/details/88016361?spm=1001.2014.3001.5502
import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.xml.XmlBeanFactory;import org.springframework.core.io.ClassPathResource;public class XmlBeanFactoryTest {public static void main(String[] args) {// 资源加载ClassPathResource classPathResource = new ClassPathResource("spring-bean.xml");// XmlBeanFactory 加载资源并解析注册beanBeanFactory beanFactory = new XmlBeanFactory(classPathResource);// BeanFactory.getBean();UserBean userBean = (UserBean) beanFactory.getBean("userBean");System.out.println(userBean.getName());}}
BeanFactory.getBean()
/*** 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.* @param typeCheckOnly whether the instance is obtained for a type check,* not for actual use* @return an instance of the bean* @throws BeansException if the bean could not be created*/@SuppressWarnings("unchecked")protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {final String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.Object sharedInstance = getSingleton(beanName);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 + "'");}}bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();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);}try {final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dependsOnBean : dependsOn) {getBean(dependsOnBean);registerDependentBean(dependsOnBean, beanName);}}// Create bean instance.if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {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 '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {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;}
doGetBean的源码比较长,那它都做了哪些事情呢: 1:转换对应的beanname,可能有很多人不理解,传入进来的不就应该是beanName嘛,其实传入的可能是BeanFactory,也可能是别名,如果是BeanFactory,就要去除它的修饰符,比如传入进来的&aa,就要转换成aa,但如果传入进来的是别名,就要取alias对应的最终的beanName,例如别名A指向了B的bean则返回B的beanName,如果别名A指向了别名B,别名B指向了C,则要返回C的BeanName; 2:检查单例中是否存在实例,会先从缓存中获取,下面会详细讲解; 3:判断原型实例是否存在循环依赖,比如A中有B,B中有A,这种情况只有单例模式才会尝试去创建,因为单例模式会提早包曝光实例,存在缓存中,原型模式是不允许的,会抛出类正在创建异常; 4:通过父BeanFactory获取bean; 5:将指定的bean标记为已经创建(或即将创建)。这允许bean工厂优化其缓存 6:获取RootBeanDefinition,在XmlBeanFactory解析的时候会将bean注册到beanDefinitionMap中,这里就是在beanDefinitionMap中get,如果不存在则会抛出bean not found异常,同时会将GenericBeanDefinition转换成RootBeanDefinition,因为存入时时GenericBeanDefinition; 7:检查BeanDefinition是否是abstract,如果是则抛出,bean is Aastract异常; 8:检查依赖,保证该bean所以依赖的bean都已经初始化,首先这里要了解depends-on用来表示一个bean A的实例化依靠另一个bean B的实例化, 但是A并不需要持有一个B的对象,如果需要的话就不用depends-on;不理解可以看这篇文章 9:判断bean的类型,是single还是proptotype,对应的创建bean,或者没有指定scope的判断,其中出现最多的方法就是getObjectForBeanInstance,后续会一点点的解析它的源码;
getSingleton(beanName);
/*** Return the (raw) singleton object registered under the given name.* <p>Checks already instantiated singletons and also allows for an early* reference to a currently created singleton (resolving a circular reference).* @param beanName the name of the bean to look for* @param allowEarlyReference whether early references should be created or not* @return the registered singleton object, or {@code null} if none found*/protected Object getSingleton(String beanName, boolean allowEarlyReference) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return (singletonObject != NULL_OBJECT ? singletonObject : null);}
单例缓存获取:首先单例是只允许创建一次,并且单例支持解决循环依赖,第一步会从singletonObjects Map中获取单例,如果发现不存在的话,再通过singletonsCurrentlyInCreation判断下当前bean是否在创建,如果是则从提前曝光的Map earlySingletonObjects中获取,如果依旧不能存在则在singletonFactories中获取BeanFactory,通过getBean进行返回,反之结束了,缓存没有,只能去重新创建了;
