曾经在项目开发中,需要实现手动生成spring bean,并将bean交由spring容器中管理的功能,费尽脑汁无从下手。最近在看spring MVC源码时,偶然发现其有相应的解决办法,其最终通过DefaultListableBeanFactory来完成。在此小记一下解决问题的过程!
以上是springMVC中,DispatcherServlet的diagram。其继承FrameworkServlet,FrameworkServlet继承HttpServletBean,HttpServletBean继承HttpServlet。HttpServlet属于serlvet规范,当Tomcat启动时,调用其init方法,最终调用到了DispatcherServlet的onRefresh方法。
关键代码在onRefresh中,初始化了springMVC执行过程中需要的对象,包括HandlerMappings、HandlerAdapters等。
private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties"; static { try { //加载DispatcherServlet.properties中内容 ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class); defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); } catch (IOException ex) { throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage()); } //初始化DispatcherServlet.properties文件中的类 protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
DispatcherServlet.properties内容:
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\ org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
在initHandlerMappings方法中,会去完成动态生成HandlerMappingbean,具体方法:
protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) { return context.getAutowireCapableBeanFactory().createBean(clazz); }
通过容器获取DefaultListableBeanFactory
①调用其父类AbstractAutowireCapableBeanFactory的createBean方法,可将class对象转化为一个spring bean,并完成IOC,这也正是笔者想要实现的功能;
②DefaultListableBeanFactory中的registerSingleton方法可完成将bean注册到spring单例池中。
大功告成!!!
当然,DefaultListableBeanFactory中还有好多功能,如getbean、注册、解析等。笔者再遇到其他用法时,后续更新。