Spring Boot 在自定义类中使用组件? [关闭]
Posted
技术标签:
【中文标题】Spring Boot 在自定义类中使用组件? [关闭]【英文标题】:Spring Boot use component in a custom class? [closed] 【发布时间】:2021-10-03 19:02:12 【问题描述】:我有一个 redis 工具:
@Component
public class RedisUtil
@Autowired
private StringRedisTemplate stringRedisTemplate;
public StringRedisTemplate getStringRedisTemplate()
return this.stringRedisTemplate;
我想在我不想成为组件的自定义类中使用它。
public class UserFeature
public String result;
public String someMethod()
var redisUtil = new RedisUtil();
var stringRedisTemplate = redisUtil.getStringRedisTemplate();
...
this.result = query_result_from_stringRedisTemplate;
当我像上面那样使用它时,它会引发一个 bean 错误。 我该怎么办?
【问题讨论】:
你为什么不在UserFeature
中注入RedisUtil
你有什么理由让UserFeature
不是一个组件?
UserFeature
有其他可以修改的属性
当我更改代码时会引发错误 - 告诉我们错误是什么。
【参考方案1】:
如果您有充分的理由创建不应由 spring 管理的对象,但仍需要使用 spring bean,则可以创建一个工厂组件,将 spring bean 注入到非 spring 对象中。
@Component
class UserFeatureFactory
private final RedisUtil redisUtil;
@Autowired
public UserFeatureFactory(RedisUtil redisUtil) ...
public UserFeature createUserFeature()
return new UserFeature(redisUtil);
// no spring annotations
class UserFeature
...
public UserFeature(RedisUtil redisUtil)
this.redisUtil = redisUtil
...
这种方法的一个很好的特点是它使UserFeature
易于测试——您只需向其构造函数传递一个模拟RedisUtil
。
【讨论】:
有更好的方法吗?这意味着我应该在所有使用 RedisUtil 的工厂函数中添加一个参数 ... 请注意,如果确实有必要,将这种依赖关系表达为Supplier<Foo>
、Function<String, Foo>
或其他名称通常是个好主意。
这很快就会变得非常乏味,但取决于必须创建的此类类的数量。
@DachuanZhao 我不太清楚你的意思?【参考方案2】:
如果由于某种原因您不能将 UserFeature
转换为组件,一般的方法是使用一个帮助程序 @Component
类,该类提供从非 Spring POJO 对 Spring bean 的访问。
@Component
public class SpringBeansProvider implements ApplicationContextAware
private static ApplicationContext context;
public static <T> T getBean(String name, Class<T> beanClass)
return context.getBean(name, beanClass);
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException
SpringBeansProvider.context = context;
然后您可以向 Spring 容器请求 RedisUtil
bean 实例:
public class UserFeature
// ...
public String someMethod()
RedisUtil redisUtil = SpringBeansProvider.getBean("redisUtil", RedisUtil.class);
// ...
此方法还允许您通过使用特定于 bean 的 getter 代替 getBean()
,轻松限制非 Spring 托管类可以访问哪些 Spring bean。
public static RedisUtil getRedisUtil()
return context.getBean("redisUtil", RedisUtil.class);
public String someMethod()
RedisUtil redisUtil = SpringBeansProvider.getRedisUtil();
// ...
【讨论】:
这种方法在各个方面都更糟糕:静态、隐藏的依赖关系以及与 Spring 上下文的紧密语义耦合。 @chrylis-cautiouslyoptimistic- 控制对 private 静态的访问,没有隐藏的依赖项——事实上,在非 Spring 代码为以后访问 Spring bean 的情况下,代码变成了自记录的审查。【参考方案3】:从 Spring 4.3 开始,类不需要任何 Spring 注释即可进行注入。只需包含一个构造函数。 (Lombok @RequiredArgsConstructor
可以为您做到这一点,它内置在 Groovy 和 Kotlin 中。)
public class MyNotComponent
private final MyComponent component;
public MyNotComponent(MyComponent component)
this.component = component;
【讨论】:
假设非 Spring 类还没有其他构造函数过于简单。以上是关于Spring Boot 在自定义类中使用组件? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
面试官:如何在自定义端口上运行 Spring Boot 应用程序?
如何在自定义反序列化器 Spring Boot 中读取路径变量或 URL 参数