您现在的位置是:首页 >学无止境 >动态加载外部springboot Jar网站首页学无止境
动态加载外部springboot Jar
简介动态加载外部springboot Jar
springboot 动态加载
背景及实现思路
想要设计一个stater,可以方便加载一个可以完整运行的springboot单体jar包,为了在已执行的服务上面快速的扩展功能而不需要重启整个服务,又或者低代码平台生成代码之后可以快速预览。
加载jar的技术栈
- springboot 2.2.6.RELEASE
- mybatis-plus 3.4.1
实现加载
想要完成类加载要熟悉spring中类加载机制,以及java中classloader的双亲委派机制。
通常bean注册过程
想要实现热加载,一定得了解在spring中类的加载机制,大体上spring在扫描到@Component注解的类时,会根据其class生成对应的BeanDefinition,然后在将其注册在BeanDefinitionRegistry(这是个接口,最终由DefaultListableBeanFactory实现)。当其备引用注入实例时即getBean时被实例化并被注册到DefaultSingletonBeanRegistry中。后续单例都将由DefaultSingletonBeanRegistry所管理。
controller加载
controller的加载机制
controller所特殊的是,spring会将其注册到RequestMappingHandlerMapping中。所以想要热加载controller 就需要三步。
- 生成并注册BeanDefinition
- 生成并注册实例
- 注册RequestMappingHandlerMapping
代码如下
// 获取bean工厂并转换为DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) ((ConfigurableApplicationContext)
applicationContext).getBeanFactory();
// 定义BeanDefinition
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionBuilder.getRawBeanDefinition();
//设置当前bean定义对象是单利的
beanDefinition.setScope("singleton");
// 将变量首字母置小写
beanName = StringUtils.uncapitalize(beanName);
// 将构建的BeanDefinition交由Spring管理
beanFactory.registerBeanDefinition(beanName, beanDefinition);
// 手动构建实例,并注入base service 防止卸载之后不再生成
Object obj = clazz.newInstance();
beanFactory.registerSingleton(beanName, obj);
log.info("register Singleton :" + beanName);
final RequestMappingHandlerMapping requestMappingHandlerMapping =
applicationContext.getBean(RequestMappingHandlerMapping.class);
if (requestMappingHandlerMapping != null) {
String handler = beanName;
Object controller = null;
try {
controller = applicationContext.getBean(handler);
} catch (Exception e) {
e.printStackTrace();
}
if (controller == null) {
return beanName;
}
// 注册Controller
Method method = requestMappingHandlerMapping.getClass().getSuperclass().getSuperclass().
getDeclaredMethod("detectHandlerMethods", Object.class);
// 将private改为可使用
method.setAccessible(true);
method.invoke(requestMappingHandlerMapping, handler);
}
controller特殊处理机制
service加载
mapper加载
其他类记载
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。