代码拉取完成,页面将自动刷新
org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
将类注册为spring beanorg.springframework.web.servlet.handler.AbstractHandlerMethodMapping#detectHandlerMethods(java.lang.Object)
,将spring-bean解析为controller工具类SpringRegister
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* spring 注册器
*
* @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @since 2022/6/28 13:31
*/
@Slf4j
public final class SpringRegister {
private SpringRegister() {
throw new UnsupportedOperationException("non-support create SpringRegister instance.");
}
/**
* 注册spring bean
*
* @see SpringRegister#registerBean(ApplicationContext, Class, String, String)
*/
public static String registerBean(ApplicationContext applicationContext, Class<?> clazz) {
String beanName = StringUtils.uncapitalize(clazz.getSimpleName());
beanName = StringUtils.uncapitalize(beanName);
return registerBean(applicationContext, clazz, beanName, "singleton");
}
/**
* 注册spring bean
*
* @see SpringRegister#registerBean(ApplicationContext, Class, String, String)
*/
public static String registerBean(ApplicationContext applicationContext, Class<?> clazz, String beanName) {
return registerBean(applicationContext, clazz, beanName, "singleton");
}
/**
* 注册spring bean
*
* @param applicationContext
* spring上下文
* @param clazz
* 要注册的class
* @param beanName
* bean name
* @param scope
* 作用域
*
* @return bean name
*/
public static String registerBean(ApplicationContext applicationContext, Class<?> clazz, String beanName,
String scope) {
Object bean = null;
try {
bean = applicationContext.getBean(beanName);
} catch (Exception e) {
// ignore
}
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
// 设置当前bean的作用域
beanDefinition.setScope(scope);
// 将applicationContext转换为ConfigurableApplicationContext
ConfigurableApplicationContext configurableApplicationContext =
(ConfigurableApplicationContext) applicationContext;
// 获取bean工厂并转换为DefaultListableBeanFactory
DefaultListableBeanFactory defaultListableBeanFactory =
(DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
if (bean != null) {
log.warn("A bean with name '" + beanName + "' has already been defined. It is '" + bean + "'. We try to "
+ "overriding it with bean '" + beanDefinition + "'.");
}
defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinition);
log.debug("register bean '" + beanName + "' success.");
return beanName;
}
/**
* 将指定bean解析controller bean
* <br>
* 核心是利用{@link AbstractHandlerMethodMapping#detectHandlerMethods(java.lang.Object)},将spring-bean解析为controller
*
* @param applicationContext
* spring上下文
* @param beanName
* 要解析的spring bean
*/
public static void registerController(ApplicationContext applicationContext, String beanName) {
// step1. 检查beanName存在
Object bean = null;
try {
bean = applicationContext.getBean(beanName);
} catch (Exception e) {
// ignore
}
if (bean == null) {
throw new RuntimeException("non-exist spring bean whose name is [" + beanName + "]. Please register it "
+ "first.");
}
// step2. 将beanName解析为controller
try {
RequestMappingHandlerMapping requestMappingHandlerMapping =
applicationContext.getBean(RequestMappingHandlerMapping.class);
Method method =
requestMappingHandlerMapping.getClass().getSuperclass().getSuperclass().getDeclaredMethod(
"detectHandlerMethods", Object.class);
boolean accessible = method.isAccessible();
method.setAccessible(true);
method.invoke(requestMappingHandlerMapping, beanName);
method.setAccessible(accessible);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException("registerController occur exception.", e);
}
log.debug("register controller-bean '" + beanName + "' success.");
}
}
要动态注册的controller
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.HashMap;
import java.util.Map;
public class NormalController {
@GetMapping("/fa")
public ResponseEntity<Map<String, Object>> methodAbc(@RequestParam("name") String name,
@RequestParam("age") Integer age) {
Map<String, Object> data = new HashMap<>(4);
data.put("name", name);
data.put("age", age);
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(data);
}
}
进行注册
import com.example.registercontroller.register.NormalController;
import com.example.registercontroller.register.SpringRegister;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class RegisterControllerApplication implements ApplicationRunner {
@Autowired
ApplicationContext applicationContext;
public static void main(String[] args) {
SpringApplication.run(RegisterControllerApplication.class, args);
}
@Override
public void run(ApplicationArguments args) throws Exception {
// 第一步:利用`org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition`将类注册为spring bean
String beanName = SpringRegister.registerBean(applicationContext, NormalController.class);
// 第二步:利用`org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#detectHandlerMethods(java.lang.Object)`,将spring-bean解析为controller
SpringRegister.registerController(applicationContext, beanName);
}
}
启动项目,访问测试
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。