Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
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 doScan(String... basePackages) {
Set beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
//findCandidateComponents方法扫描class文件,将有Component注解的类转换成BeanDefinition. 该类注解包括@Component、@Controller、@Service、@Repository。
Set 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;
}