如何在程序运行期间,动态生成spring bean,并放入spring 容器中?

曾经在项目开发中,需要实现手动生成spring bean,并将bean交由spring容器中管理的功能,费尽脑汁无从下手。最近在看spring MVC源码时,偶然发现其有相应的解决办法,其最终通过DefaultListableBeanFactory来完成。在此小记一下解决问题的过程!

如何在程序运行期间,动态生成spring bean,并放入spring 容器中?_第1张图片 

 以上是springMVC中,DispatcherServlet的diagram。其继承FrameworkServlet,FrameworkServlet继承HttpServletBean,HttpServletBean继承HttpServlet。HttpServlet属于serlvet规范,当Tomcat启动时,调用其init方法,最终调用到了DispatcherServlet的onRefresh方法。

如何在程序运行期间,动态生成spring bean,并放入spring 容器中?_第2张图片 

 关键代码在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、注册、解析等。笔者再遇到其他用法时,后续更新。

如何在程序运行期间,动态生成spring bean,并放入spring 容器中?_第3张图片

你可能感兴趣的:(如何在程序运行期间,动态生成spring bean,并放入spring 容器中?)