在本文中,您将会了解到关于简单的Spring,将ClasspathApplicationContext用于独立的应用程序,如何重用?的新资讯,同时我们还将为您解释spring中的classpath的相
在本文中,您将会了解到关于简单的Spring,将ClasspathApplicationContext用于独立的应用程序,如何重用?的新资讯,同时我们还将为您解释spring中的classpath的相关在本文中,我们将带你探索简单的Spring,将ClasspathApplicationContext用于独立的应用程序,如何重用?的奥秘,分析spring中的classpath的特点,并给出一些关于ClassPathXMLApplicationContext 上下文加载过程、ClassPathXmlApplicationContext 加载 spring 配置文件、ClassPathXMLApplicationContext上下文加载过程、ClassPathXmlApplicationContext类的实用技巧。
本文目录一览:- 简单的Spring,将ClasspathApplicationContext用于独立的应用程序,如何重用?(spring中的classpath)
- ClassPathXMLApplicationContext 上下文加载过程
- ClassPathXmlApplicationContext 加载 spring 配置文件
- ClassPathXMLApplicationContext上下文加载过程
- ClassPathXmlApplicationContext类
简单的Spring,将ClasspathApplicationContext用于独立的应用程序,如何重用?(spring中的classpath)
如果我有一个独立的主应用程序。说20堂课。它们都可能随时需要与spring配置(ApplicationContext)定义的bean接口。我将在主应用程序入口点引导类路径应用程序上下文。但是,如何重用已经实例化的bean?
例如,将ClasspathApplicationContext设置为单例似乎是一种不好的方法,但这就是这个主意。
我以为我已经看到了GlobalContextLocator或类似的东西,但是没有看到如何使用它的示例。
答案1
小编典典有很多方法可以做到这一点。最好的参考在这里:
http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#context-
introduction
您需要查看的特定类是SingletonBeanFactoryLocator和ContextSingletonBeanFactoryLocator。
如果使用SingletonBeanFactoryLocator,则可以使用以下内容查找bean:
BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance();BeanFactoryReference bf = bfl.useBeanFactory("com.mycompany.myapp");MyClass zed = bf.getFactory().getBean("mybean");
Javadocs中对此有很好的详细解释:
http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/access/SingletonBeanFactoryLocator.html
另外,为了清楚起见,请确保配置文件位于应用程序的类路径中,否则查找将失败。
ClassPathXMLApplicationContext 上下文加载过程
今天看了一下《spring 技术内幕》,看了下 spring IOC 容器的加载过程,但是里面的代码很杂,就自己用源码的测试用例 debug 了一下看了下过程
测试用例
@Test
public void testSingleConfigLocation() throws IOException {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(FQ_SIMPLE_CONTEXT);
assertTrue(ctx.containsBean("someMessageSource"));
LazyBean bean = ctx.getBean(LazyBean.class);
Environment environment =ctx.getEnvironment();
String[] profiles =environment.getDefaultProfiles();
for(String s :profiles){
System.out.println(s);
}
CollectionBean bean2 = (CollectionBean) ctx.getBean("collection");
SingletonBean bean3 = ctx.getBean(SingletonBean.class);
SingletonBean bean4 = ctx.getBean(SingletonBean.class);
if (bean != null) {
System.out.println(bean.getTestFiled());
}
if (bean2 != null) {
System.out.println(bean2.getList());
}
if (bean3 != null) {
bean3.process();
}
if (bean4 != null) {
bean4.process();
}
System.out.println(ctx.getBeanDefinitionCount());
/*
* System.out.println(ctx.getBean("lazyBean"));
* System.out.println(ctx.getBean("lazyBean"));
*/
ctx.close();
}
加载过程
- 首先会调用父类 AbstractApplicationContext 的静态初始化块
static {
// Eagerly load the ContextClosedEvent class to avoid weird classloader issues
// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
ContextClosedEvent.class.getName();
}
大概就是说为了避免一些奇怪的问题会首先发布一个 ContextClosedEvent 事件,然后按照正常的初始化依次初始化父类。
- 调用构造方法中的 refresh 方法,这个方法也是上下文初始化的开始
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
- refresh 方法会调用 AbstractRefreshableApplicationContext 中的 refreshBeanFactory 方法创建一个 DefaultListableBeanFactory 实例,作为上下文的容器
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
- 创建了容器之后就要从 xml 文件中加载和注册 bean 的定义,上面的 loadBeanDefinition 方法在 AbstractXmlApplicationContext 中的实现会被调用
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, 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.setEnvironment(this.getEnvironment());
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);
}
/**
* Initialize the bean definition reader used for loading the bean
* definitions of this context. Default implementation is empty.
* <p>Can be overridden in subclasses, e.g. for turning off XML validation
* or using a different XmlBeanDefinitionParser implementation.
* @param reader the bean definition reader used by this context
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setDocumentReaderClass
*/
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
reader.setValidating(this.validating);
}
/**
* Load the bean definitions with the given XmlBeanDefinitionReader.
* <p>The lifecycle of the bean factory is handled by the {@link #refreshBeanFactory}
* method; hence this method is just supposed to load and/or register bean definitions.
* @param reader the XmlBeanDefinitionReader to use
* @throws BeansException in case of bean registration errors
* @throws IOException if the required XML document isn''t found
* @see #refreshBeanFactory
* @see #getConfigLocations
* @see #getResources
* @see #getResourcePatternResolver
*/
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
- 这两个方法会用来加载并注册 BeanDefiniton,它们又会使用 XmlBeanDefinitionReader 来加载 xml 中的 bean 的定义,bean 定义的解析会使用 DefaultBeanDefinitionDocumentReader,它又会使用 BeanDefinitionParserDelegate 类委托解析 bean 的定义
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//委托BeanDefinitionParserDelegate进行解析
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name ''" +
bdHolder.getBeanName() + "''", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
上面黑体标注的是将解析的 BeanDefinition 注册到上下文中的过程,我之前没找到这个方法很奇怪 loadBeanDefinition 返回的都是 int 我就在想,BeanDefinition 哪去了。静态方法会调用 BeanDefinitionRegistry
接口的 registerBeanDefinition 方法。而 DefaultListableBeanFactory 实现了这个接口,
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
到此 BeanDefinition 就被注册到了 ClassPathXmlApplicationContext 中,还有很多细节没贴出来,自己 debug 一下很有意思的
ClassPathXmlApplicationContext 加载 spring 配置文件
通过 ClassPathXmlApplicationContext 加载 spring 配置文件 但是有两个配置文件中 bean 互相依赖 先加载哪个配置文件 都会出现 BeanCreationException 求指点ClassPathXMLApplicationContext上下文加载过程
今天看了一下《spring技术内幕》,看了下spring IOC容器的加载过程,但是里面的代码很杂,就自己用源码的测试用例debug了一下看了下过程
测试用例
@Test public void testSingleConfigLocation() throws IOException { ClasspathXmlApplicationContext ctx = new ClasspathXmlApplicationContext(FQ_SIMPLE_CONTEXT); assertTrue(ctx.containsBean("someMessageSource")); LazyBean bean = ctx.getBean(LazyBean.class); Environment environment =ctx.getEnvironment(); String[] profiles =environment.getDefaultProfiles(); for(String s :profiles){ System.out.println(s); } CollectionBean bean2 = (CollectionBean) ctx.getBean("collection"); SingletonBean bean3 = ctx.getBean(SingletonBean.class); SingletonBean bean4 = ctx.getBean(SingletonBean.class); if (bean != null) { System.out.println(bean.getTestFiled()); } if (bean2 != null) { System.out.println(bean2.getList()); } if (bean3 != null) { bean3.process(); } if (bean4 != null) { bean4.process(); } System.out.println(ctx.getBeanDeFinitionCount()); /* * System.out.println(ctx.getBean("lazyBean")); * System.out.println(ctx.getBean("lazyBean")); */ ctx.close(); }
加载过程
- 首先会调用父类AbstractApplicationContext的静态初始化块
static { // Eagerly load the ContextClosedEvent class to avoid weird classloader issues // on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.) ContextClosedEvent.class.getName(); }
大概就是说为了避免一些奇怪的问题会首先发布一个ContextClosedEvent事件,然后按照正常的初始化依次初始化父类。
- 调用构造方法中的refresh方法,这个方法也是上下文初始化的开始
public ClasspathXmlApplicationContext( String[] configLocations,boolean refresh,@Nullable ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); } }
- refresh方法会调用AbstractRefreshableApplicationContext中的refreshbeanfactory方法创建一个DefaultListablebeanfactory实例,作为上下文的容器
protected final void refreshbeanfactory() throws BeansException { if (hasbeanfactory()) { destroyBeans(); closebeanfactory(); } try { DefaultListablebeanfactory beanfactory = createbeanfactory(); beanfactory.setSerializationId(getId()); customizebeanfactory(beanfactory); loadBeanDeFinitions(beanfactory); synchronized (this.beanfactoryMonitor) { this.beanfactory = beanfactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean deFinition source for " + getdisplayName(),ex); } }
- 创建了容器之后就要从xml文件中加载和注册bean的定义,上面的loadBeanDeFinition方法在AbstractXmlApplicationContext中的实现会被调用
@Override protected void loadBeanDeFinitions(DefaultListablebeanfactory beanfactory) throws BeansException,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.setEnvironment(this.getEnvironment()); 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); } /** * Initialize the bean deFinition reader used for loading the bean * deFinitions of this context. Default implementation is empty. * <p>Can be overridden in subclasses,e.g. for turning off XML validation * or using a different XmlBeanDeFinitionParser implementation. * @param reader the bean deFinition reader used by this context * @see org.springframework.beans.factory.xml.XmlBeanDeFinitionReader#setDocumentReaderClass */ protected void initBeanDeFinitionReader(XmlBeanDeFinitionReader reader) { reader.setValidating(this.validating); } /** * Load the bean deFinitions with the given XmlBeanDeFinitionReader. * <p>The lifecycle of the bean factory is handled by the {@link #refreshbeanfactory} * method; hence this method is just supposed to load and/or register bean deFinitions. * @param reader the XmlBeanDeFinitionReader to use * @throws BeansException in case of bean registration errors * @throws IOException if the required XML document isn‘t found * @see #refreshbeanfactory * @see #getConfigLocations * @see #getResources * @see #getResourcePatternResolver */ protected void loadBeanDeFinitions(XmlBeanDeFinitionReader reader) throws BeansException,IOException { Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDeFinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDeFinitions(configLocations); } }
- 这两个方法会用来加载并注册BeanDefiniton,它们又会使用XmlBeanDeFinitionReader来加载xml中的bean的定义,bean定义的解析会使用DefaultBeanDeFinitionDocumentReader,它又会使用BeanDeFinitionParserDelegate类委托解析bean的定义
protected void processBeanDeFinition(Element ele,BeanDeFinitionParserDelegate delegate) {
//委托BeanDeFinitionParserDelegate进行解析 BeanDeFinitionHolder bdHolder = delegate.parseBeanDeFinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDeFinitionIfrequired(ele,bdHolder); try { // Register the final decorated instance. BeanDeFinitionReaderUtils.registerBeanDeFinition(bdHolder,getReaderContext().getRegistry()); } catch (BeanDeFinitionStoreException ex) { getReaderContext().error("Failed to register bean deFinition with name ‘" + bdHolder.getBeanName() + "‘",ele,ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDeFinition(bdHolder)); } }
上面黑体标注的是将解析的BeanDeFinition注册到上下文中的过程,我之前没找到这个方法很奇怪loadBeanDeFinition返回的都是int我就在想,BeanDeFinition哪去了。静态方法会调用BeanDeFinitionRegistry
接口的registerBeanDeFinition方法。而DefaultListablebeanfactory实现了这个接口,
public static void registerBeanDeFinition( BeanDeFinitionHolder deFinitionHolder,BeanDeFinitionRegistry registry) throws BeanDeFinitionStoreException { // Register bean deFinition under primary name. String beanName = deFinitionHolder.getBeanName(); registry.registerBeanDeFinition(beanName,deFinitionHolder.getBeanDeFinition()); // Register aliases for bean name,if any. String[] aliases = deFinitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registeralias(beanName,alias); } } }
到此BeanDeFinition就被注册到了ClasspathXmlApplicationContext中,还有很多细节没贴出来,自己debug一下很有意思的
ClassPathXmlApplicationContext类
org.springframework.context.support
Class ClassPathXmlApplicationContext
java.lang.Object
org.springframework.core.io.DefaultResourceLoader
org.springframework.context.support.AbstractApplicationContext
org.springframework.context.support.AbstractRefreshableApplicationContext
org.springframework.context.support.AbstractRefreshableConfigApplicationContext
org.springframework.context.support.AbstractXmlApplicationContext
org.springframework.context.support.ClassPathXmlApplicationContext
- All Implemented Interfaces:
- BeanFactory, BeanNameAware, DisposableBean, HierarchicalBeanFactory, InitializingBean, ListableBeanFactory, ApplicationContext, ApplicationEventPublisher, ConfigurableApplicationContext, Lifecycle, MessageSource, ResourceLoader, ResourcePatternResolver
-
public class ClassPathXmlApplicationContext
- extends AbstractXmlApplicationContext
该类继承了AbstractXmlApplicationContext,实现了BeanFctory和ApplicationContext接口。
使用BeanFactory接口还是ApplicationContext接口?
BeanFactory只是实现了Spring基本的功能,而ApplicationContext添加了更多的功能,并且ApplicationContext完全支持BeanFactory的所有功能,ApplicationContext建立于BeanFactory基础之上的。ApplicationContext是BeanFactory的子接口,而BeanFactory是ApplicationContext的父接口。所以,建议优先使用ApplicationContext接口。
官方文档解释:
In short, the BeanFactory
provides the configuration framework and basic functionality, and the ApplicationContext
adds more enterprise-specific functionality. The ApplicationContext
is a complete superset of the BeanFactory
今天关于简单的Spring,将ClasspathApplicationContext用于独立的应用程序,如何重用?和spring中的classpath的介绍到此结束,谢谢您的阅读,有关ClassPathXMLApplicationContext 上下文加载过程、ClassPathXmlApplicationContext 加载 spring 配置文件、ClassPathXMLApplicationContext上下文加载过程、ClassPathXmlApplicationContext类等更多相关知识的信息可以在本站进行查询。
本文标签: