`

多多研究Spring3源码

    博客分类:
  • J2EE
 
阅读更多
最近自己写一个Ioc容器。
基本上全部采用直接方式支持Ioc,
至于XML,能不用就不用,那个烦死人的东西。

其中遇见很多问题,还是一步一步解决了不少。
其实多多看看spring3的源码是很有帮助的,呵呵。
这个方法应该是spring ioc里面一个很重要的方法了。在org.springframework.beans.factory.support.AbstractBeanFactory这个类中
/**
	 * 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);
			}

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

		// 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;
	}

可能没有研究过Spring源码的同学不知道这个方法。
其实你每次使用getBean(String beanName) 和 getBean(Class clazz)还有getBean(String beanName,Clazz clazz)这些方法的时候,最终都是回到了doGetBean这个方法。
public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}

	public Object getBean(String name, Object... args) throws BeansException {
		return doGetBean(name, null, args, false);
	}

public <T> T getBean(Class<T> requiredType) throws BeansException {
		Assert.notNull(requiredType, "Required type must not be null");
		String[] beanNames = getBeanNamesForType(requiredType);
		if (beanNames.length > 1) {
			ArrayList<String> autowireCandidates = new ArrayList<String>();
			for (String beanName : beanNames) {
				if (getBeanDefinition(beanName).isAutowireCandidate()) {
					autowireCandidates.add(beanName);
				}
			}
			if (autowireCandidates.size() > 0) {
				beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
			}
		}
		if (beanNames.length == 1) {
			return getBean(beanNames[0], requiredType);
		}
		else if (beanNames.length == 0 && getParentBeanFactory() != null) {
			return getParentBeanFactory().getBean(requiredType);
		}
		else {
			throw new NoSuchBeanDefinitionException(requiredType, "expected single bean but found " +
					beanNames.length + ": " + StringUtils.arrayToCommaDelimitedString(beanNames));
		}
	}

看doGetBean()方法定义就知道这是一个泛型方法,所以咯。使用getBean(Class clazz)这个方法的时候就不用强制转型咯。

有大部分我都还没有研究进去,不过不急,慢慢看。。。。
分享到:
评论

相关推荐

    javaweb电子商城源代码

    【JavaWeb电子商城源代码】是一个基于JavaWeb技术开发的电子商务平台项目,它为学习者和开发者提供了深入了解和实践Web应用程序开发的宝贵资源。这个源代码涵盖了从用户界面设计到后端业务逻辑处理的全套流程,是...

    四酷全书源代码

    通过深入研究这些源代码,开发者不仅可以学习到各种编程语言和技术,还能了解良好的编程实践、版本控制、代码组织结构以及软件工程的其他方面。这是一份宝贵的资源,对于初学者来说,可以帮助他们快速掌握编程技能;...

    [已测试]拼多多客京东客蘑菇街小程序V10.0.8完整全解密后端源码+小程序前端.zip

    3. **后端源码**:后端源码主要包括服务器端的编程语言(如Java、Python或Node.js)、数据库设计(如MySQL、MongoDB)、框架(如Django、Spring Boot、Express)以及业务逻辑的实现。通过源码,开发者可以了解到如何...

    多个分类随机海量高清壁纸系统源码.zip

    该压缩包文件“多个分类随机海量高清壁纸系统源码.zip”包含了开发一个高清壁纸应用的完整源代码。这个系统能够提供多个分类的壁纸,并且具备随机展示海量高清壁纸的功能。重要的是,它并非依赖于第三方接口,而是...

    研究生调研管理系统springboot

    网页采用sprngboot+vue技术开发,java作为后台代码,技术用到springmvc, 所有程序保证可以运行,项目功能参考文章,如遇到运行不了请联系作者获取源码,源码制作不易, 希望多多支持给予好评。 二、项目技术 开发...

    外卖小程序的研究与开发ssm

    所有程序保证可以运行,项目功能参考文章,如遇到运行不了请联系作者获取源码,源码制作不易, 希望多多支持给予好评。 二、项目技术 开发语言:Java 数据库:MySQL 项目管理工具:Maven 后端技术:SSM(Spring+...

    毕业设计-MeyboMail Web(Java)开源简化-meybomailweb项目源码

    【MeyboMail Web(Java)开源简化-meybomailweb项目源码】是一个针对Java开发人员的毕业设计项目,旨在提供一个基于Web的邮件系统实现。该项目以开源的形式,简化了邮件服务的开发流程,使开发者可以更快地理解和构建...

    淘宝、京东、拼多多优惠券+PC端网站+微信小程序+合伙人代理,有安装教程.zip

    用户可以通过阅读源代码、研究架构设计,甚至尝试修改和扩展功能,来提升自己的技能。 总的来说,这个压缩包提供的项目涵盖了电商平台的核心功能,对于想要深入理解电商系统开发、微信小程序开发以及分销模式的...

    java独立pdd最新的代码.rar

    Java独立PDD支付出码源码是针对拼多多电商平台的一个支付解决方案,主要涉及到的是Java编程语言在处理支付业务方面的技术实现。这个源码包包含了最新的代码更新,意味着它可能包括了性能优化、新功能添加或者对已有...

    仿PDD拼团系统微信拼团系统全功能商业版内附详细配置文档+参数对接文档.zip

    这个压缩包的文件名“仿PDD拼团系统微信拼团系统全功能商业版内附详细配置文档+参数对接文档.rar”表明,除了系统源代码或安装包之外,还包含了详细的配置文档和参数对接文档。配置文档通常会指导用户如何安装和设置...

    基于微信小程序和SSM的社区团购小程序开题报告.doc

    采用微信小程序作为前端,利用SpringBoot和SSM(Spring、SpringMVC、MyBatis)框架构建后端,可以实现快速开发,同时充分利用微信的社交特性,增强用户粘性。 四、技术实现 在技术实现上,微信小程序的开发需要...

Global site tag (gtag.js) - Google Analytics