⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractautowirecapablebeanfactory.java

📁 spring的源代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
			throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
																			"Error setting property values", ex);
		}
	}

	/**
	 * Given a PropertyValue, return a value, resolving any references to other
	 * beans in the factory if necessary. The value could be:
	 * <li>A BeanDefinition, which leads to the creation of a corresponding
	 * new bean instance. Singleton flags and names of such "inner beans"
	 * are always ignored: Inner beans are anonymous prototypes.
	 * <li>A RuntimeBeanReference, which must be resolved.
	 * <li>A ManagedList. This is a special collection that may contain
	 * RuntimeBeanReferences or Collections that will need to be resolved.
	 * <li>A ManagedSet. May also contain RuntimeBeanReferences or
	 * Collections that will need to be resolved.
	 * <li>A ManagedMap. In this case the value may be a RuntimeBeanReference
	 * or Collection that will need to be resolved.
	 * <li>An ordinary object or null, in which case it's left alone.
	 */
	protected Object resolveValueIfNecessary(String beanName, RootBeanDefinition mergedBeanDefinition,
																					 String argName, Object value) throws BeansException {
		// We must check each PropertyValue to see whether it
		// requires a runtime reference to another bean to be resolved.
		// If it does, we'll attempt to instantiate the bean and set the reference.
		if (value instanceof AbstractBeanDefinition) {
			BeanDefinition bd = (BeanDefinition) value;
			if (bd instanceof AbstractBeanDefinition) {
				// an inner bean should never be cached as singleton
				((AbstractBeanDefinition) bd).setSingleton(false);
			}
			String innerBeanName = "(inner bean for property '" + beanName + "." + argName + "')";
			Object bean = createBean(innerBeanName, getMergedBeanDefinition(innerBeanName, bd));
			if (bean instanceof DisposableBean) {
				// keep reference to inner bean, to be able to destroy it on factory shutdown
				this.disposableInnerBeans.add(bean);
			}
			return getObjectForSharedInstance(innerBeanName, bean);
		}
		else if (value instanceof RuntimeBeanReference) {
			RuntimeBeanReference ref = (RuntimeBeanReference) value;
			return resolveReference(beanName, mergedBeanDefinition, argName, ref);
		}
		else if (value instanceof ManagedList) {
			// Convert from managed list. This is a special container that may
			// contain runtime bean references. May need to resolve references.
			return resolveManagedList(beanName, mergedBeanDefinition, argName, (ManagedList) value);
		}
		else if (value instanceof ManagedSet) {
			// Convert from managed set. This is a special container that may
			// contain runtime bean references. May need to resolve references.
			return resolveManagedSet(beanName, mergedBeanDefinition, argName, (ManagedSet) value);
		}
		else if (value instanceof ManagedMap) {
			// Convert from managed map. This is a special container that may
			// contain runtime bean references. May need to resolve references.
			ManagedMap mm = (ManagedMap) value;
			return resolveManagedMap(beanName, mergedBeanDefinition, argName, mm);
		}
		else {
			// no need to resolve value
			return value;
		}
	}

	/**
	 * Resolve a reference to another bean in the factory.
	 */
	protected Object resolveReference(String beanName, RootBeanDefinition mergedBeanDefinition,
																		String argName, RuntimeBeanReference ref) throws BeansException {
		try {
			logger.debug("Resolving reference from property '" + argName + "' in bean '" +
			             beanName + "' to bean '" + ref.getBeanName() + "'");
			return getBean(ref.getBeanName());
		}
		catch (BeansException ex) {
			throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
																			"Can't resolve reference to bean '" + ref.getBeanName() +
																			"' while setting property '" + argName + "'", ex);
		}
	}

	/**
	 * For each element in the ManagedList, resolve reference if necessary.
	 */
	protected List resolveManagedList(String beanName, RootBeanDefinition mergedBeanDefinition,
																		String argName, ManagedList ml) throws BeansException {
		List resolved = new ArrayList();
		for (int i = 0; i < ml.size(); i++) {
			resolved.add(resolveValueIfNecessary(beanName, mergedBeanDefinition, argName + "[" + i + "]", ml.get(i)));
		}
		return resolved;
	}

	/**
	 * For each element in the ManagedList, resolve reference if necessary.
	 */
	protected Set resolveManagedSet(String beanName, RootBeanDefinition mergedBeanDefinition,
																	String argName, ManagedSet ms) throws BeansException {
		Set resolved = new HashSet();
		for (Iterator it = ms.iterator(); it.hasNext();) {
			resolved.add(resolveValueIfNecessary(beanName, mergedBeanDefinition, argName + "[(set-element)]", it.next()));
		}
		return resolved;
	}

	/**
	 * For each element in the ManagedMap, resolve reference if necessary.
	 */
	protected Map resolveManagedMap(String beanName, RootBeanDefinition mergedBeanDefinition,
																	String argName, ManagedMap mm) throws BeansException {
		Map resolved = new HashMap();
		Iterator keys = mm.keySet().iterator();
		while (keys.hasNext()) {
			Object key = keys.next();
			resolved.put(key, resolveValueIfNecessary(beanName, mergedBeanDefinition, argName + "[" + key + "]", mm.get(key)));
		}
		return resolved;
	}

	/**
	 * Give a bean a chance to react now all its properties are set,
	 * and a chance to know about its owning bean factory (this object).
	 * This means checking whether the bean implements InitializingBean
	 * and/or BeanFactoryAware, and invoking the necessary callback(s) if it does.
	 * @param bean new bean instance we may need to initialize
	 * @param beanName the bean has in the factory. Used for debug output.
	 */
	protected void invokeInitMethods(String beanName, RootBeanDefinition mergedBeanDefinition, Object bean)
			throws Exception {

		if (bean instanceof InitializingBean) {
			logger.debug("Calling afterPropertiesSet() on bean with beanName '" + beanName + "'");
			((InitializingBean) bean).afterPropertiesSet();
		}

		if (mergedBeanDefinition.getInitMethodName() != null) {
			logger.debug("Calling custom init method '" + mergedBeanDefinition.getInitMethodName() +
									 "' on bean with beanName '" + beanName + "'");
			try {
				bean.getClass().getMethod(mergedBeanDefinition.getInitMethodName(), null).invoke(bean, null);
			}
			catch (InvocationTargetException ex) {
				throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
																				"Initialization method '" + mergedBeanDefinition.getInitMethodName() +
																				"' threw exception", ex.getTargetException());
			}
			catch (Exception ex) {
				throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
																				"Invocation of initialization method '" +
																				mergedBeanDefinition.getInitMethodName() + "' failed", ex);
			}
		}
	}

	public void destroySingletons() {
		super.destroySingletons();

		synchronized (this.disposableInnerBeans) {
			for (Iterator it = this.disposableInnerBeans.iterator(); it.hasNext();) {
				Object bean = it.next();
				it.remove();
				destroyBean("(inner bean of type " + bean.getClass().getName() + ")", bean);
			}
		}
	}

	protected void destroyBean(String beanName, Object bean) {
		logger.debug("Retrieving depending beans for bean '" + beanName + "'");
		String[] dependingBeans = getDependingBeanNames(beanName);
		if (dependingBeans != null) {
			for (int i = 0; i < dependingBeans.length; i++) {
				destroySingleton(dependingBeans[i]);
			}
		}

		logger.debug("Applying DestructionAwareBeanPostProcessors to bean with name '" + beanName + "'");
		for (int i = getBeanPostProcessors().size() - 1; i >= 0; i--) {
			Object beanProcessor = getBeanPostProcessors().get(i);
			if (beanProcessor instanceof DestructionAwareBeanPostProcessor) {
				((DestructionAwareBeanPostProcessor) beanProcessor).postProcessBeforeDestruction(bean, beanName);
			}
		}

		if (bean instanceof DisposableBean) {
			logger.debug("Calling destroy() on bean with name '" + beanName + "'");
			try {
				((DisposableBean) bean).destroy();
			}
			catch (Exception ex) {
				logger.error("destroy() on bean with name '" + beanName + "' threw an exception", ex);
			}
		}

		try {
			RootBeanDefinition bd = getMergedBeanDefinition(beanName, false);
			if (bd.getDestroyMethodName() != null) {
				logger.debug("Calling custom destroy method '" + bd.getDestroyMethodName() +
										 "' on bean with name '" + beanName + "'");
				invokeCustomDestroyMethod(beanName, bean, bd.getDestroyMethodName());
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// ignore, from manually registered singleton
		}
	}

	/**
	 * Invoke the specified custom destroy method on the given bean.
	 * <p>This implementation invokes a no-arg method if found, else checking
	 * for a method with a single boolean argument (passing in "true",
	 * assuming a "force" parameter), else logging an error.
	 * <p>Can be overridden in subclasses for custom resolution of destroy
	 * methods with arguments.
	 */
	protected void invokeCustomDestroyMethod(String beanName, Object bean, String destroyMethodName) {
		Method[] methods = bean.getClass().getMethods();
		Method targetMethod = null;
		for (int i = 0; i < methods.length; i++) {
			if (methods[i].getName().equals(destroyMethodName)) {
				if (targetMethod == null ||
						methods[i].getParameterTypes().length < targetMethod.getParameterTypes().length) {
					targetMethod = methods[i];
				}
			}
		}
		if (targetMethod == null) {
			logger.error("Couldn't find a method named '" + destroyMethodName +
									 "' on bean with name '" + beanName + "'");
		}
		else {
			Class[] paramTypes = targetMethod.getParameterTypes();
			if (paramTypes.length > 1) {
				logger.error("Method '" + destroyMethodName + "' of bean '" + beanName +
										 "' has more than one parameter - not supported as destroy method");
			}
			else if (paramTypes.length == 1 && !paramTypes[0].equals(boolean.class)) {
				logger.error("Method '" + destroyMethodName + "' of bean '" + beanName +
										 "' has a non-boolean parameter - not supported as destroy method");
			}
			else {
				Object[] args = new Object[paramTypes.length];
				if (paramTypes.length == 1) {
					args[0] = Boolean.TRUE;
				}
				try {
					targetMethod.invoke(bean, args);
				}
				catch (InvocationTargetException ex) {
					logger.error("Couldn't invoke destroy method '" + destroyMethodName +
											 "' of bean with name '" + beanName + "'", ex.getTargetException());
				}
				catch (Exception ex) {
					logger.error("Couldn't invoke destroy method '" + destroyMethodName +
											 "' of bean with name '" + beanName + "'", ex);
				}
			}
		}
	}


	//---------------------------------------------------------------------
	// Abstract methods to be implemented by concrete subclasses
	//---------------------------------------------------------------------

	/**
	 * Find bean instances that match the required type. Called by autowiring.
	 * If a subclass cannot obtain information about bean names by type,
	 * a corresponding exception should be thrown.
	 * @param requiredType the type of the beans to look up
	 * @return a Map of bean names and bean instances that match the required type,
	 * or null if none found
	 * @throws BeansException in case of errors
	 * @see #autowireByType
	 * @see #autowireConstructor
	 */
	protected abstract Map findMatchingBeans(Class requiredType) throws BeansException;

	/**
	 * Return the names of the beans that depend on the given bean.
	 * Called by destroyBean, to be able to destroy depending beans first.
	 * @param beanName name of the bean to find depending beans for
	 * @return array of names of depending beans, or null if none
	 * @throws BeansException in case of errors
	 * @see #destroyBean
	 */
	protected abstract String[] getDependingBeanNames(String beanName) throws BeansException;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -