Spring如何基于URL参数动态创建运行时Bean并自动注入Access类
解决方案
首先明确核心前提:Spring默认的单例Bean依赖注入是容器启动阶段完成的,你当前写法的问题在于Access如果是默认单例Bean,启动时就会尝试注入Student实例,此时还没有用户请求生成参数,必然会注入失败,且单例Bean的依赖注入完成后不会自动更新。你可以按照以下步骤实现需求:
步骤1:在控制器中动态注册Student Bean
先改造FunRestController,注入Spring上下文,拿到请求参数后手动创建Student实例并注册到IoC容器:
@RestController public class FunRestController { // 注入Spring上下文 @Autowired private ApplicationContext context; @GetMapping("/{id}/{name}") public String welcomeToBoot(@PathVariable int id, @PathVariable String name) { // 1. 用请求参数创建Student实例 Student student = new Student(id, name); // 2. 获取BeanFactory用于动态注册Bean DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getAutowireCapableBeanFactory(); // 3. 若已存在同名Bean先移除,避免重复注册报错 if (beanFactory.containsBean("student")) { beanFactory.removeBeanDefinition("student"); } // 4. 注册Student为单例Bean beanFactory.registerSingleton("student", student); return "Welcome " + name; } }
步骤2:改造Access类适配动态Bean
有两种可选方案,根据你的业务场景选择:
方案A:将Access改为请求作用域(推荐无并发冲突场景)
每次请求生成新的Access实例,注入当前请求对应的Student:
// 加@Component交给Spring管理,加@RequestScope设置为请求作用域 @Component @RequestScope public class Access { @Autowired Student s; void print() { System.out.println(s.name); } }
方案B:动态从容器中获取Student(推荐Access需要保持单例的场景)
不提前注入Student,每次调用方法时实时从容器拉取最新实例:
@Component public class Access { @Autowired private ApplicationContext context; void print() { // 实时获取最新的Student实例 Student s = context.getBean(Student.class); System.out.println(s.name); } }
并发场景优化建议
如果是多用户同时访问的场景,直接注册单例Student会出现后请求的参数覆盖前一个的问题,此时更推荐直接将Student声明为请求作用域Bean,不需要手动动态注册:
@Component @RequestScope public class Student { public int id; public String name; // 补充无参构造和setter方法 public Student() {} public void setId(int id) {this.id = id;} public void setName(String name) {this.name = name;} }
在控制器中直接注入Student赋值即可:
@RestController public class FunRestController { @Autowired private Student student; @GetMapping("/{id}/{name}") public String welcomeToBoot(@PathVariable int id, @PathVariable String name) { student.setId(id); student.setName(name); return "Welcome " + name; } }
内容的提问来源于stack exchange,提问作者Ramu
相关产品推荐
相关产品推荐

