/** * Load the template BeanDefinition and call {@link #transform(ConfigurableListableBeanFactory, * BeanDefinition, Element, ParserContext)} to apply runtime configuration value to it. <code> * builder</code> will be configured to instantiate the bean in the Spring context that we are * parsing. * * <p>During parsing, an instance of {@link * TemplateBeanDefinitionParser.TemplateComponentDefinition} is pushed onto <code>ParserContext * </code> so that nested tags can access the enclosing template configuration with a call to * {@link #findEnclosingTemplateFactory(ParserContext)}. Subclasses can override {@link * #newComponentDefinition(String, Object, DefaultListableBeanFactory)} to provide a subclass of * {@link TemplateBeanDefinitionParser.TemplateComponentDefinition} to the parser context if * necessary. */ @Override protected final void doParse( Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { // if we have multiple nested bean definitions, we only parse the template factory // once. this allows configuration changes made by enclosing bean parsers to be inherited // by contained beans, which is quite useful. DefaultListableBeanFactory templateFactory = findEnclosingTemplateFactory(parserContext); TemplateComponentDefinition tcd = null; if (templateFactory == null) { // no nesting -- load the template XML configuration from the classpath. final BeanFactory parentFactory = (BeanFactory) parserContext.getRegistry(); templateFactory = new DefaultListableBeanFactory(parentFactory); // load template bean definitions DefaultResourceLoader loader = new DefaultResourceLoader(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(templateFactory); reader.setResourceLoader(loader); reader.setEntityResolver(new ResourceEntityResolver(loader)); reader.loadBeanDefinitions(templateResource); // propagate factory post-processors from the source factory into the template // factory. BeanDefinition ppChain = new RootBeanDefinition(ChainingBeanFactoryPostProcessor.class); ppChain.getPropertyValues().addPropertyValue("targetFactory", templateFactory); parserContext.getReaderContext().registerWithGeneratedName(ppChain); // push component definition onto the parser stack for the benefit of // nested bean definitions. tcd = newComponentDefinition( element.getNodeName(), parserContext.extractSource(element), templateFactory); parserContext.pushContainingComponent(tcd); } try { // allow subclasses to apply overrides to the template bean definition. BeanDefinition def = templateFactory.getBeanDefinition(templateId); transform(templateFactory, def, element, parserContext); // setup our factory bean to instantiate the modified bean definition upon request. builder.addPropertyValue("beanFactory", templateFactory); builder.addPropertyValue("beanName", templateId); builder.getRawBeanDefinition().setAttribute("id", def.getAttribute("id")); } finally { if (tcd != null) parserContext.popContainingComponent(); } }
/** * Loads the bean definitions via an XmlBeanDefinitionReader. * * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader * @see #initBeanDefinitionReader * @see #loadBeanDefinitions */ protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
/** * 通过XmlBeanDefinitionReader 来加载bean definition.第三步. * * <p>当然,可能存在其他非xml形式的配置加载,所以这个从refreshablApplicationConetext类中抽象出模板方法,在子类来实现 * * <p>Loads the bean definitions via an XmlBeanDefinitionReader. * * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader * @see #initBeanDefinitionReader * @see #loadBeanDefinitions */ @Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // DefaultListableBeanFactory 中实现了BeanDefinitionRegistry ,reader会将解析好的bean definition 注册到该对象上 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // 配置资源使用的环境,一般用的比较少,打包一般只配置对应的环境配置 beanDefinitionReader.setEnvironment(this.getEnvironment()); // this 继承了 DefaultResourceLoader类,所以其如果不是classpath的话,最终会调用filesystem的getResourcebypath // 实际上,这就是程序式ioc的第一步,定义resourceLoader beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // 允许子类提供自定义的reader初始化,然后进行实际的加载bean definition工作 initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
/*初始化方法*/ public void init() { beanDefinitionReader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) applicationContext.getBeanFactory()); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(applicationContext)); }