全量刷新上下文代码示例:
package com.kfyty.demo; import com.kfyty.loveqq.framework.boot.K; import com.kfyty.loveqq.framework.boot.context.ContextRefresher; import com.kfyty.loveqq.framework.core.autoconfig.annotation.Autowired; import com.kfyty.loveqq.framework.core.autoconfig.annotation.BootApplication; import com.kfyty.loveqq.framework.core.autoconfig.annotation.Component; import com.kfyty.loveqq.framework.core.autoconfig.condition.annotation.ConditionalOnProperty; import com.kfyty.loveqq.framework.core.autoconfig.env.PropertyContext; import com.kfyty.loveqq.framework.core.utils.IOC; import com.kfyty.loveqq.framework.web.core.annotation.GetMapping; import com.kfyty.loveqq.framework.web.core.annotation.RestController; import com.kfyty.loveqq.framework.web.core.autoconfig.annotation.EnableWebMvc; import lombok.extern.slf4j.Slf4j; @Slf4j @EnableWebMvc @RestController @BootApplication public class Main { public static void main(String[] args) throws Exception { K.run(Main.class, args); } @Autowired private UserService userService; @Autowired private PropertyContext propertyContext; /** * 调用接口方法 */ @GetMapping public String sayHello() { return userService.hello(); } /** * 通过可刷新的配置属性切换 UserService 实现类 * * @param impl 条件配置属性 */ @GetMapping public String switchUserImpl(String impl) { // 设置可刷新的属性,刷新上下文时不会丢失 propertyContext.setRefreshProperty("user.service.impl", impl); // 全量刷新上下文,由于类已加载,刷新过程会很快 ContextRefresher.refresh(IOC.getApplicationContext()); // 刷新是异步的,这里返回页面提示 return "ok"; } /** * 接口定义 */ public interface UserService { String hello(); } /** * 扩展实现 */ @Component @ConditionalOnProperty(value = "user.service.impl", havingValue = "extension") public static class ExtensionUserService extends DefaultUserService { @Override public String hello() { return "internal"; } } /** * 默认实现 */ @Component @ConditionalOnProperty(value = "user.service.impl", havingValue = "default", matchIfMissing = true) public static class DefaultUserService implements UserService { @Override public String hello() { return "default"; } } }
上述代码启动 main 方法后:
- 先访问:http://localhost:8080/sayHello,将返回 default
- 然后访问:http://localhost:8080/switchUserImpl?impl=internal,此时将进行ioc容器的全量刷新
- 然后再访问:http://localhost:8080/sayHello,将返回 internal,原因是条件注解生效,实现类变化了!
从而实现了热更新类实现,这是 @RefreshScope 注解所无法实现的效果。
并且由于是热更新,所以ioc容器的刷新很快完成(ms 级别),相比重新启动耗时更短。
还没有评论,来说两句吧...