- 浏览: 61255 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
liwanfeng:
看楼上的评价不错,但是格式可能是je改版,现在看格式比较乱啊! ...
Spring DispatcherServlet MVC 源码分析(Webapplicationcontext的生成) -
pian_yun:
我的理解是,没事实例化的function xxx(){}里面的 ...
Javascript的关于this用法的一个问题的分析 -
yxgd:
...
Spring ProxyFactoryBean是如何代理Class分析 -
charles_zuo:
讲解的很详细,按照LZ的分析看了下源码,条理很清晰,谢谢
Spring DispatcherServlet MVC 源码分析(Webapplicationcontext的生成) -
sorphi:
再贴一篇,关于是否能自动判断post方式提交过来的数据编码
...
Servlet 乱码问题
BeanFactory的初始化的触发——><o:p></o:p>
FrameworkServlet中的wac.refresh()<o:p></o:p>
<o:p> </o:p>
如下为初始化MVC部分的操作:<o:p></o:p>
- initmultipartresolver();
- initlocaleresolver();
- initthemeresolver();
- inithandlermappings();
- inithandleradapters();
- inithandlerexceptionresolvers();
- initviewresolver();
<o:p></o:p>
<o:p> </o:p>
现在有一个疑问 initHandlerMappings(ApplicationContext context)中的ApplicationContext的实现在web中是哪一个,可以从下面得到结论<o:p></o:p>
<o:p> </o:p>
- public static final Class DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
- private Class contextClass = DEFAULT_CONTEXT_CLASS;
<o:p></o:p>
<o:p> </o:p>
可以看出这个地方是实例化的是XmlWebApplicationContext的一个实例,那么这个实例是在哪个地方被实例化的呢?在DispatchServelet的父类FrameworkServlet中可以找到如下的代码,<o:p></o:p>
<o:p> </o:p>
- WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
- WebApplicationContext wac = createWebApplicationContext(parent);
<o:p></o:p>
<o:p> </o:p>
ok,我们现在就可以用这个wac了,顺便看看这个实例里边都有什么东西:<o:p></o:p>
<o:p> </o:p>
- wac.setParent(parent);//web.xml中加载的context
- wac.setServletContext(getServletContext());
- wac.setServletConfig(getServletConfig());
- wac.setNamespace(getNamespace());
- if (getContextConfigLocation() != null) {
- wac.setConfigLocations(
- StringUtils.tokenizeToStringArray(
- getContextConfigLocation(), ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
- }//比较有用
- wac.addApplicationListener(this);
<o:p></o:p>
<o:p> </o:p>
继续我们的MVC探索--><o:p></o:p>
下面是MVC的部分,提前分析一下<o:p></o:p>
- protected List getDefaultStrategies(ApplicationContext context, Class strategyInterface) throws BeansException {
- String key = strategyInterface.getName();//equals org.springframework.web.servlet.HandlerMapping
- List strategies = null;
- String value = defaultStrategies.getProperty(key);
- //org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping.class
- if (value != null) {
- String[] classNames = StringUtils.commaDelimitedListToStringArray(value);//等效于split
- strategies = new ArrayList(classNames.length);
- for (int i = 0; i < classNames.length; i++) {
- String className = classNames[i];
- try {
- Class clazz = ClassUtils.forName(className, getClass().getClassLoader());
- Object strategy = createDefaultStrategy(context, clazz);
- strategies.add(strategy);
- }
- catch (ClassNotFoundException ex) {
- throw new BeanInitializationException(
- "Could not find DispatcherServlet's default strategy class [" + className +
- "] for interface [" + key + "]", ex);
- }
- catch (LinkageError err) {
- throw new BeanInitializationException(
- "Error loading DispatcherServlet's default strategy class [" + className +
- "] for interface [" + key + "]: problem with class file or dependent class", err);
- }
- }
- }else {
- strategies = Collections.EMPTY_LIST;
- }
- return strategies;
- }
- protected Object createDefaultStrategy(ApplicationContext context, Class clazz) throws BeansException {
- return context.getAutowireCapableBeanFactory().createBean(
- clazz, AutowireCapableBeanFactory.AUTOWIRE_NO, false);
- //org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping.class
- }
<o:p></o:p>
context 为XmlWebApplicationContext的一个实例,而<o:p></o:p>
<o:p> </o:p>
- public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext
- public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableApplicationContext
- implements ConfigurableWebApplicationContext, ThemeSource
- public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext
- public abstract class AbstractApplicationContext extends DefaultResourceLoader
- implements ConfigurableApplicationContext, DisposableBean {
- public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
- return getBeanFactory();
- }
- }
- 在AbstractRefreshableApplicationContext中
- public final ConfigurableListableBeanFactory getBeanFactory() {
- synchronized (this.beanFactoryMonitor) {
- if (this.beanFactory == null) {
- throw new IllegalStateException("BeanFactory not initialized or already closed - " +
- "call 'refresh' before accessing beans via the ApplicationContext");
- }
- return this.beanFactory;
- }
- }
<o:p>
说明这个时候BeanFactory已经初始化好了,那么在哪个地方初始化好的呢?可以想象到的地方就是XmlWebApplicationContext在new的时候会初始化这个BeanFactory?在WebApplicationContext createWebApplicationContext(WebApplicationContext parent)时候,也就是在初始化ApplicationContext的时候有如下操作<o:p></o:p>
<o:p> </o:p>
wac.refresh();<o:p></o:p>
<o:p> </o:p>
也就是初始化ApplicationContext之后会马上初始化BeanFacory<o:p></o:p>
从类结构里我们能找到这个方法来自它的父类: AbstractApplicationContext 在它的 refresh() 方法内我们可以看到 spring 的复杂逻辑。首先执行了refreshBeanFactory(); (来自 AbstractRefreshableApplicationContext )见 (a),<o:p></o:p>
<o:p> </o:p>
(a)refreshBeanFactory(); 这个方法由负责维护变量 beanFactory 的子类AbstractRefreshableApplicationContext 实现,默认情况下<o:p></o:p>
这个方法直接实例化一个新的 DefaultListableBeanFactory 类型的 BeanFacorty, <o:p></o:p>
- protected final void refreshBeanFactory() throws BeansException {
- DefaultListableBeanFactory beanFactory = createBeanFactory();
- customizeBeanFactory(beanFactory);
- loadBeanDefinitions(beanFactory);
- }
- protected DefaultListableBeanFactory createBeanFactory() {
- return new DefaultListableBeanFactory(getInternalParentBeanFactory());
- }
- AbstractApplicationContext.java
- protected BeanFactory getInternalParentBeanFactory() {//判断用的是ApplicationContext or BeanFactory
- return (getParent() instanceof ConfigurableApplicationContext) ?
- ((ConfigurableApplicationContext) getParent()).getBeanFactory() : (BeanFactory) getParent();
- }
- public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
- implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {}
- XmlWebApplicationContext.java-->
- /**
- * 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);
- }
- public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
- }
- XmlBeanDefinitionReader 继承了 AbstractBeanDefinitionReader,AbstractBeanDefinitionReader的构造函数如下:
- protected AbstractBeanDefinitionReader(BeanDefinitionRegistry beanFactory) {//DefaultListableBeanFactory实现了
- //BeanDefinitionRegistry
- Assert.notNull(beanFactory, "Bean factory must not be null");
- this.beanFactory = beanFactory;
- // Determine ResourceLoader to use.如果beanFactory不但实现了BeanDefinitionRegistry,而且实现了ResourceLoader
- //通常的这样的情况是实现了org.springframework.context.ApplicationContext的BeanFactory,这一点可以查看(c)部分
- if (this.beanFactory instanceof ResourceLoader) {
- this.resourceLoader = (ResourceLoader) this.beanFactory;
- }else {
- this.resourceLoader = new PathMatchingResourcePatternResolver();
- }
- }
<o:p></o:p>
初始化完了AbstractBeanDefinitionReader之后,继续XmlBeanDefinitionReaderd的初始化:<o:p></o:p>
- public XmlBeanDefinitionReader(BeanDefinitionRegistry beanFactory) {
- if (getResourceLoader() != null) {//getResourceLoader已经得到
- this.entityResolver = new ResourceEntityResolver(getResourceLoader());
- //entityResolver
- }else {
- this.entityResolver = new DelegatingEntityResolver(ClassUtils.getDefaultClassLoader());
- }
- }
<o:p></o:p>
上面的初始化相当于初始化了 XmlBeanDefinitionReader的resourceLoader和entityResolver<o:p></o:p>
然后就是对各个配置路径的初始化工作:<o:p></o:p>
- protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
- String[] configLocations = getConfigLocations();
- if (configLocations != null) {
- for (int i = 0; i < configLocations.length; i++) {
- reader.loadBeanDefinitions(configLocations[i]);
- }
- }
- }
<o:p></o:p>
XmlBeanDefinitionReader中的初始化工作,因此所有的xml的解析实际上是在这个类文件中完成的 <o:p></o:p>
- public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
- InputStream inputStream = encodedResource.getResource().getInputStream();
- try {
- InputSource inputSource = new InputSource(inputStream);
- if (encodedResource.getEncoding() != null) {
- inputSource.setEncoding(encodedResource.getEncoding());
- }
- return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
- }
- finally{
- inputStream.close();
- }
- }catch (IOException ex) {
- throw new BeanDefinitionStoreException(
- "IOException parsing XML document from " + encodedResource.getResource(), ex);
- }
- }
- protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
- throws BeanDefinitionStoreException {
- int validationMode = getValidationModeForResource(resource);
- Document doc = this.documentLoader.loadDocument(//获得解析的dom路径
- inputSource, this.entityResolver, this.errorHandler, validationMode, this.namespaceAware);
- return registerBeanDefinitions(doc, resource);
- }
- (c)
- public abstract class AbstractApplicationContext extends DefaultResourceLoader
- implements ConfigurableApplicationContext, DisposableBean{};//AbstractApplicationContext继承了DefaultResourceLoader
- public class DefaultResourceLoader implements ResourceLoader{}//DefaultResourceLoader实现了ResourceLoader
- public DefaultResourceLoader() {//构造函数
- this.classLoader = ClassUtils.getDefaultClassLoader();
- }
- public static ClassLoader getDefaultClassLoader() {
- cl = Thread.currentThread().getContextClassLoader();//取得Application级的ClassLoader
- }
<o:p></o:p>
<o:p> </o:p>
<o:p> </o:p>
然后调用一个起缓冲作用的配置函数生成一个将 beanFacroty 包装起来的对象 beanDefinitionReader ,然后对这个对象进行属性配置,实际上该方法主要负责生成一个临时的操作对象,对应调用的函数为“loadBeanDefinitions(beanFactory);”该方法为初始化期间较为重要的一个。该方法来自其子类:AbstractRefreshableWebApplicationContext <o:p></o:p>
<o:p>
- protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
- String[] configLocations = getConfigLocations();// xml文件的配置的路径
- if (configLocations != null) {
- for (int i = 0; i < configLocations.length; i++) {
- reader.loadBeanDefinitions(configLocations[i]);
- }
- }
- }
<o:p>
对应的函数:<o:p></o:p>
protected void loadBeanDefinitions(DefaultListableBeanFactory) ,然后这里又调用了自己定义的 <o:p></o:p>
protected void loadBeanDefinitions(XmlBeanDefinitionReader) 方法。此时,它就使用到了在以前中设置了的( wac.setConfigLocations(……)) 我们开发中密切相关的配置文件。(同时也要记住此时这个函数的参数 beanDefinitionReader ,之前已经设置了”beanDefinitionReader.setResourceLoader(this) “这里的 this 是我们在前面见到的 XmlWebApplicationContext (一个定义好了的上下文))。接着往下:reader.loadBeanDefinitions(configLocations[i]); reader 开始加载我们配置文件内的东西了,不过真正复杂的实现此时才开始,我们继续往下走,在接下来的方法内默认情况下会执行:if (resourceLoader instanceof ResourcePatternResolver)(该判断条件为true ),由于从上面我们知道: beanDefinitionReader.setResourceLoader(this); 而 this 的类型为: XmlWebApplicationContext所以 ((ResourcePatternResolver) resourceLoader).getResources(location); 得到一个 Resource[] 数组,接下来调用:int loadCount = loadBeanDefinitions(resources); 该函数继续调用自己子类定义的一系列临时接口最终执行到 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); 在这个函数内初始化了处理 xml 文件的一些对象并将用户的配置文件解析为一个 Document 对象。然后又执行了一系列函数直到return parser.registerBeanDefinitions(this, doc, resource); 这个函数来自我们新建的 DefaultXmlBeanDefinitionParser,在这个类里最终执行了对 xml 文件的解析工作和对 beanFacroty 变量执行了设置工作。<o:p></o:p>
<o:p> </o:p>
(b)终于我们从这些繁杂的逻辑中跳了出来,继续执行 AbstractApplicationContext.refresh() 下面的工作,后续的代码主要仍旧是往一些常量里面设值。<o:p></o:p>
<o:p> </o:p>
此时 Spring BeanFactory初始化过程就结束了。发表评论
-
Spring DispatcherServlet MVC 源码分析(Webapplicationcontext的生成)
2007-08-25 09:26 3991<servlet></servlet> ... -
Spring 源码分析(Log4jConfigListener Parts)
2007-08-25 09:21 5074java 代码 Spring O ... -
Spring Open Sourse Research(ContextLoaderListener Parts)
2007-08-25 09:21 2987Spring 源码分析(ContextLoaderListe ... -
Spring ProxyFactoryBean是如何代理Class分析
2007-08-25 09:19 40651、ProxyFactoryBean 把proxy的创建交给A ...
相关推荐
在Spring框架的源码中,BeanFactory是管理bean的核心接口,它负责bean的实例化、初始化、装配和查找。而ApplicationContext是BeanFactory的扩展,增加了对国际化、事件传播、资源加载等功能,它是Spring应用的主要...
在Spring MVC应用中,DispatcherServlet作为Web层的核心,在web.xml中配置后,它会负责整个Web层的初始化工作,包括加载HandlerMapping、Controller等。 HandlerMapping用于将HTTP请求映射到对应的Controller处理器...
源码分析是理解Spring工作原理的关键,能帮助开发者深入掌握如何在实际项目中有效地使用和优化Spring。下面将对Spring框架的核心组件、设计理念以及源码中的关键部分进行详细的解释。 1. **依赖注入(DI)** - ...
8. **事件驱动**:Spring框架允许应用在特定事件(如bean的初始化或销毁)发生时进行响应。`ApplicationEvent`和`ApplicationListener`接口是实现事件驱动的关键。 9. **国际化与本地化**:Spring提供了`...
- **Bean的生命周期**:从BeanFactory到ApplicationContext,了解Bean的实例化、初始化、依赖注入、作用域和销毁过程。 - **AOP(面向切面编程)**:理解切点、通知、代理等概念,以及如何在Spring中实现AOP。 - ...
1. **配置DispatcherServlet**:在 web.xml 文件中配置 DispatcherServlet,指定初始化参数以加载 Spring 配置文件。 2. **定义控制器**:控制器类需要使用 `@Controller` 注解标记,方法上可以使用 `@...
通过 `ApplicationContext` 的测试版,我们可以方便地在测试环境中初始化和管理 Bean。 总的来说,Spring 2.5 源码包是一份宝贵的教育资源,它揭示了 Spring 框架的强大功能和优雅设计。通过学习这些源码,开发者...
例如,DispatcherServlet的初始化过程中,会通过BeanFactory获取所有配置的HandlerMapping和HandlerAdapter,这体现了IoC;而拦截器的链式调用则是AOP的应用。 工具方面,Spring MVC与IDE(如Eclipse、IntelliJ ...
Bean的生命周期包括初始化、使用和销毁三个阶段,开发者可以自定义这些阶段的行为。 在Web环境中,通常使用Servlet监听器来加载`applicationContext.xml`,并使用`FileSystemXmlApplicationContext`或`...
在这个模块中,我们可以深入理解BeanFactory和ApplicationContext的区别,以及如何自定义bean的初始化和销毁行为。 4. `org.springframework.web.servlet`:这部分源码主要处理HTTP请求,实现了MVC架构。我们能从中...
它负责管理对象的生命周期和装配,源码里可以学习到Bean的创建、初始化、配置和查找过程。 4. **数据访问抽象层**:Spring 提供了对各种数据存取技术的抽象,包括JDBC、ORM(如Hibernate、MyBatis)、OXM(对象-XML...
源码中的注释将帮助我们理解`BeanFactory`和`ApplicationContext`是如何加载和管理Bean的生命周期,包括初始化、装配、销毁等过程。此外,我们还可以通过注释了解`@Component`、`@Service`、`@Repository`和`@...
1. **ApplicationContext**:这是Spring的核心接口,负责初始化、加载配置文件,管理Bean的生命周期。源码中可以看到它是如何解析XML或Java配置,创建并管理Bean的。 2. **BeanFactory**:作为ApplicationContext的...
1. **Bean的生命周期**:研究BeanFactory和ApplicationContext接口,了解如何加载和管理Bean,以及Bean的初始化、销毁过程。 2. **AOP的实现**:查看AOP代理(JDK动态代理和CGLIB)的实现,理解切面如何织入目标...
1. org.springframework.web.servlet.DispatcherServlet:这是 Spring MVC 的入口点,源码中可以看到它如何初始化 MVC 配置,并进行请求调度。 2. org.springframework.web.servlet.mvc.method.annotation....
`BeanDefinition`类是Bean的元信息,它包含Bean的类型、初始化方法、依赖关系等信息。`BeanPostProcessor`接口允许自定义Bean的后处理器,可以在Bean实例化前后执行自定义逻辑。 在AOP部分,`Aspect`和`Advice`是...
Spring管理的对象称为Bean,其生命周期包括初始化、正常运行以及销毁三个阶段。BeanFactory和ApplicationContext提供了各种回调方法,如init-method、postProcessBeforeInitialization、...
在这个版本中,你将看到如何通过`BeanFactory`和`ApplicationContext`接口来管理bean的实例化、初始化、装配和销毁。 `spring-context`模块扩展了`spring-beans`,引入了上下文的概念,提供了更丰富的特性,如AOP...
Spring 4 源码分析 Spring 是一个广泛使用的开源 Java 框架,它以其模块化、灵活性和全面的企业级应用支持而闻名。Spring 4 版本引入了许多改进和新特性,使得开发者能够更高效地构建和管理应用程序。在深入研究 ...
源码中,`BeanFactory`和`ApplicationContext`定义了对bean的创建、初始化、容器中的注册以及销毁的接口方法。 3. **AOP(面向切面编程)** - AOP使得我们可以在不修改业务代码的情况下,对程序进行功能增强,如...