spring scope实现原理

继续前面章节的分析,回到AbstractBeanFactory中对bean的获取代码上面来:点击打开链接

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

			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() {
					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() {
						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);
				}
			}
		}

		// 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 (T) bean;
	}

   可见,当bean的scope是prototype的时候,直接创建一个新object.这个object用完自然也就回收了,没啥好说的。

            当bean的scope是singleton的时候,在DefaultSingletonBeanRegistry下面有一个map负责维护singleton   bean的缓存。生命周期就是容器的生命周期。

 

  最后到了非prototype,非singleton的情况。

  这种情况下需要从scope里面获取。

 

   在当前线程下面有一个绑定的RequestAttributes,scope就是通过这个RequestAttributes来获取维护的bean的信息。查看一下这个接口的实现类:ServletRequestAttributes,里面的getAttribute方法实现了对bean的获取:

 

Java代码   收藏代码
  1. public Object getAttribute(String name, int scope) {  
  2.         if (scope == SCOPE_REQUEST) {  
  3.             if (!isRequestActive()) {  
  4.                 throw new IllegalStateException(  
  5.                         "Cannot ask for request attribute - request is not active anymore!");  
  6.             }  
  7.             return this.request.getAttribute(name);  
  8.         }  
  9.         else {  
  10.             HttpSession session = getSession(false);  
  11.             if (session != null) {  
  12.                 try {  
  13.                     Object value = session.getAttribute(name);  
  14.                     if (value != null) {  
  15.                         synchronized (this.sessionAttributesToUpdate) {  
  16.                             this.sessionAttributesToUpdate.put(name, value);  
  17.                         }  
  18.                     }  
  19.                     return value;  
  20.                 }  
  21.                 catch (IllegalStateException ex) {  
  22.                     // Session invalidated - shouldn't usually happen.  
  23.                 }  
  24.             }  
  25.             return null;  
  26.         }  
  27.     }  
public Object getAttribute(String name, int scope) {
		if (scope == SCOPE_REQUEST) {
			if (!isRequestActive()) {
				throw new IllegalStateException(
						"Cannot ask for request attribute - request is not active anymore!");
			}
			return this.request.getAttribute(name);
		}
		else {
			HttpSession session = getSession(false);
			if (session != null) {
				try {
					Object value = session.getAttribute(name);
					if (value != null) {
						synchronized (this.sessionAttributesToUpdate) {
							this.sessionAttributesToUpdate.put(name, value);
						}
					}
					return value;
				}
				catch (IllegalStateException ex) {
					// Session invalidated - shouldn't usually happen.
				}
			}
			return null;
		}
	}

    可见,当scope是requestscope的时候,bean建立之后放在request里面,需要时取出。

             当scopde是sessionscope/globalsessionscope的时候,bean建立之后放在session/globalsession里面,需要时取出。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值