Spring5源码分析(一)

简述

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

Bean加载

ClassPathXmlApplicationContext类继承关系图

public ClassPathXmlApplicationContext(
		String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
		throws BeansException {
	super(parent);
	setConfigLocations(configLocations);
	if (refresh) {
		refresh();
	}
}

Spring通过ApplicationContext类,将Xml和基于注解配置的Bean加载到Spring 容器中进行统一管理,以ClassPathXmlApplicationContext类为例。在创建一个ClassPathXmlApplicationContext的对象时,最终通过父类AbstractApplicationContext的refresh()方法,该方法主要完成了自定义bean的初始化,并注册了listener等其它bean。

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {

		// 获取bean工厂,根据Xml中的配置信息加载
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
		prepareBeanFactory(beanFactory);
		try {
		//进行非自定义类的加载,以及一些其他步骤
			postProcessBeanFactory(beanFactory);
			invokeBeanFactoryPostProcessors(beanFactory);
			registerBeanPostProcessors(beanFactory);
			initMessageSource();
			initApplicationEventMulticaster();
			onRefresh();
			registerListeners();
			finishBeanFactoryInitialization(beanFactory);
			finishRefresh();
		}catch(Exception e){
		}
}

prepareBeanFactory()方法最终会调用到AbstractXmlApplicationContext类的loadBeanDefinitions(XmlBeanDefinitionReader reader)方法,调用到AbstractBeanDefinitionReader的loadBeanDefinitions(String location, @Nullable Set actualResources)方法,将Xml配置文件的信息转成Resource,并最终调用子类XmlBeanDefinitionReader的doLoadBeanDefinitions(InputSource inputSource, Resource resource)方法

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource){
	Document doc = doLoadDocument(inputSource, resource);
	int count = registerBeanDefinitions(doc, resource);
	if (logger.isDebugEnabled()) {
		logger.debug("Loaded " + count + " bean definitions from " + resource);
	}
	return count;
}

该方法将xml文件里的信息转换成Document后,根据document节点的信息,调用DefaultBeanDefinitionDocumentReader的parseBeanDefinitions方法

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	if (delegate.isDefaultNamespace(root)) {
		NodeList nl = root.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element) {
				Element ele = (Element) node;
				if (delegate.isDefaultNamespace(ele)) {
				    //处理默认的节点
					parseDefaultElement(ele, delegate);
				}
				else {
				    //处理自定义的节点,如
					delegate.parseCustomElement(ele);
				}
			}
		}
	}
	else {
		delegate.parseCustomElement(root);
	}
}

以自定义节点component-scan为例,在ContextNamespaceHandler中,初始化代码如下,它会将不同Parser注册到该handler对象里,对于Compoment-scan,最终会调用ComponentScanBeanDefinitionParser中的parse(Element element, ParserContext parserContext)方法,对Element元素进行处理。

public void init() {
	registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
	registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
	registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
	registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
	registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
	registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
	registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}

最终,该parse方法会调用ClassPathBeanDefinitionScanner类中的doScan(String… basePackages)方法,将带有Component注解的类解析成BeanDefinition,对于默认的Bean,解析方式相似,最终完成类加载.

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
	Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
	for (String basePackage : basePackages) {
	    //findCandidateComponents方法扫描class文件,将有Component注解的类转换成BeanDefinition. 该类注解包括@Component、@Controller、@Service、@Repository。
		Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
		for (BeanDefinition candidate : candidates) {
			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
			candidate.setScope(scopeMetadata.getScopeName());
			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
			if (candidate instanceof AbstractBeanDefinition) {
				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
			}
			if (candidate instanceof AnnotatedBeanDefinition) {
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}
			if (checkCandidate(beanName, candidate)) {
				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
				definitionHolder =
						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
				beanDefinitions.add(definitionHolder);
				registerBeanDefinition(definitionHolder, this.registry);
			}
		}
	}
	return beanDefinitions;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值