ApplicationContext 实例化后去哪里了?
假如我们在写一个基于Spring的普通应用程序,不管我们用了多么精妙的设计模式,进行了如何巧妙的设计,我们必须在某个地方执行这样的代码:
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
appContext.getBean("…");
也许这样的代码算不上丑陋,但是它无疑破坏了程序的纯洁性和透明性。我们的应用程序开始显式地依赖SpringFramework,我们必须清楚地知道Spring的配置文件有哪几个,每个配置文件的加入或修改源代码,我们必须在某些代码模块里调用丑陋的getBean方法来创造对象。
其实真正的区别只有一个,普通应用程序是一个主动执行的程序,而Web应用程序却是被动的组件。这意味着Web应用程序无法自己主动去生成自己的线程去执行某项任务,而必须借用Web容器中的一个线程。想象一下一个简单的任务:我们想每隔一段时间执行一个任务,比如说在Console里打印出一行文字。在我们的Web应用程序里应该怎么完成?在我不知道Servlet Listener或Spring里提供的Schedule之前(其实Spring就是利用Servlet Listenner初始化Application Context时启动schedule的),这么简单的任务在一个Web应用程序里竟然是不可想象。还记得我当时采用的是最傻的做法:写了一个单独的应用程序,在这应用程序的main函数里启动了timetask。
其实ApplicationContext之谜已经不再是谜了。真正的关键在于当我们的Web应用程序是被动的组件时,它除了可以错用容器的线程之外还可以错用其它一些东西。我们可以让容器来帮我们创建ApplicationContext,然后把它放在某个地方,然后在需要使用时让容器从这个地方把ApplicationContext读出来,并执行相应的Controller就可以了。
这个"某个地方"就是ServletContext,而这个创建ApplicationContext的地方就是Servlet Listner,而取到ApplicationContext的地方是我们的DispatcherServlet。
在contextloader 类里面可以看大一段代码:
this.context = createWebApplicationContext(servletContext, parent);
servletContext.setAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
如此就明白了, spring的整个框架基础 是在 servlet 标准里面的一个扩展应用罢了, 不那么神奇了
Web 程序写多了, 以至于写普通的Spring程序的时候, 在main方法中得到bean,总觉得可以用@Resource注入就好了, 应该不用去getBean嘛。
却忘了其实写Web程序的时候, applicationContext交给了web容器,是它帮我们去getBean了。 而@Resource和@AutoWired的自动注入 , 也并不是马上就注入,真正注入在某个时间, 由 容器 调用applicationContext.getBean再帮我们注入了。
注入时机:
参考:http://www.iteye.com/problems/93479
spring的bean在什么时候实例化,我说在被依赖的时候实例化.
分为以下几种Bean
1. 如果指定的是convertrService,beanPostProcessor等实例的时候,则会在ApplicationContext初始化的时候就实例化.
2. 如果指定的是自定义的Bean,那么会在第一次访问的时候实例化.
[被依赖的时候实例化,更明确的说是第一次访问]
<bean id="" name="">这样这个bean是否会被实例化
答案:不会实例化,ApplicationContext只会加载Bean的BeanDefinition.
1、lazy init 在getBean时实例化
2、非lazy的单例bean 容器初始化时实例化
3、prototype等 getBean时实例化