这是一个问题,问很多人都不清楚的问题,也许有一部分人知道spring是隐式得调用DefaultLisTableBeanFactory的父类AbstractBeanFactory的
getBean()方法来真正实例化对象的,那么,这个getBean()到底是在什么地方调用的呢?
那么,我们就来分析一下吧。
1:基于springMVC框架的项目:
  这个就很简单了,我们都知道基于spring的web项目。IOC容器初始化的入口全部在l里面:
  <listener-class>
      org.t.ContextLoaderListener
    </listener-class>
  </listener>
 
  通过这个ContextLoaderListener,spring完成了BeanDefinition的解析,注册。也就是完成了对XML配置文件的解读,并把所有定义的bean
  信息作为spring特有的数据结构存储到了BeanDefinition集合。并将这个集合作为hasMap保存在容器里。并且在这个过程中,建立了web项目的上下
  文环境。
 
  接下来,我们看springMvc的容器初始化,他是通过l的这个入口进入的。通过这个DispatcherServlet的入口,spring会再次建立一个上下
  文在DispatcherServlet建立起来的上下文之上的。
 
   <servlet>
     <servlet-name>tms</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <load-on-startup>1</load-on-startup>
    </servlet>
 <servlet-mapping>
  <servlet-name>tms</servlet-name>
  <url-pattern>*.htm</url-pattern>
 </servlet-mapping>
 
 
  好了,接下来的事情就很明显了,项目启动起来后,当一个URL请求过来的时候,就会进入 DispatcherServlet,在这个类里面,spring调用了
  getBean()方法,对URL请求需要用到的对象,都进行了实例化。
 
  我们可以看看通常我们的一个控制层的配置文件:
  <?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "/dtd/spring-beans-2.0.dtd">
<beans>
 
 
 <bean id="suggestCompletedController" class="cn.s.controller.SuggestCompletedController">
  <property name="methodNameResolver">
   <bean class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
    <property name="mappings">
     <props>       
          <prop key="/xtGetSuggestData.htm">getSuggestData</prop>
          </props>
    </property>
   
   </bean>
  </property>
        <property name="baseService" ref="baseService" />
        <property name="suggestCompletedService" ref="suggestCompletedService"/>
 </bean>
 
   
 <bean id="mbUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
      <property name="mappings">
       <props>
           
            <prop key="/yunxingList.htm">sjjEhrController</prop>
        <prop key="/getSjxByLeixingList.htm">sjjEhrController</prop>
        <prop key="/yxkSjxEdit.htm">sjjEhrController</prop>
       </props>
      </property>
 
  </bean>
 
</beans>
可以看到,控制层的所有bean定义都是需要被注入到 mbUrlMapping里面的。
我们接下来看看DispatcherServlet。他有很多init方法,其中就有一个initHandlerMappings:
 private void initHandlerMappings(ApplicationContext context) {
  this.handlerMappings = null;
  if (this.detectAllHandlerMappings) {
   // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
   Map<String, HandlerMapping> matchingBeans =
     BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
   if (!matchingBeans.isEmpty()) {
    this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
    // We keep HandlerMappings in sorted order.
    OrderComparator.sort(this.handlerMappings);
   }
  }
  else {
   try {
    HandlerMapping hm = Bean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
    this.handlerMappings = Collections.singletonList(hm);
   }
   catch (NoSuchBeanDefinitionException ex) {
    // Ignore, we'll add a default HandlerMapping later.
   }
  }
  // Ensure we have at least one HandlerMapping, by registering
  // a default HandlerMapping if no other mappings are found.
  if (this.handlerMappings == null) {
   this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
   if (logger.isDebugEnabled()) {
    logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
   }
  }
 }
 
 也就是在这个地方,spring显式的调用了
 HandlerMapping hm = Bean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
 来完成了对象的初始化工作。
 
至于为什么会来调用这个方法,是因为spring dispatcherServlet集成了httpServlet。WEB容器会自动调用他的
init()方法,这个init放在在他的父类:HttpServletBean做了实现:
 public final void init() throws ServletException {
  if (logger.isDebugEnabled()) {
   logger.debug("Initializing servlet '" + getServletName() + "'");
  }
  // Set bean properties from init parameters.
  try {
   PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), quiredProperties);
   BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
   ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
  &isterCustomEditor(Resource.class, new ResourceEditor(resourceLoader, vironment));
   initBeanWrapper(bw);     bw.setPropertyValues(pvs, true);
  }
  catch (BeansException ex) {
  &("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
实例化类和实例化对象   throw ex;
  }
  // Let subclasses do whatever initialization they like.
  initServletBean();  //这里会调用一个初始化
  if (logger.isDebugEnabled()) {
   logger.debug("Servlet '" + getServletName() + "' configured successfully");
  }
 }
 
//initServletBean方法
  protected final void initServletBean() throws ServletException {
  getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
  if (this.logger.isInfoEnabled()) {
   this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
  }
  long startTime = System.currentTimeMillis();
  try {
   this.webApplicationContext = initWebApplicationContext();  //这里进入
   initFrameworkServlet();
  }
  catch (ServletException ex) {
   ("Context initialization failed", ex);
   throw ex;
  }
  catch (RuntimeException ex) {
   ("Context initialization failed", ex);
   throw ex;
  }

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。