为什么在春季两次创建单身豆?
我有一个弹簧启动项目,其中包含bookmapper
bean:
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BookMapper {
// some CRUD methods here...
}
bean由mybatis
创建,它是singleton
。通常,我将bean与@autowired
:
@Service
public BookService {
@Autowired
private BookMapper bookMapper;
}
我也有这样的文件:
@Component
public class BeanUtil implements ApplicationContextAware {
private static ApplicationContext ac;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ac = applicationContext;
}
public static <T> T getBean(Class<T> clazz){
return ac.getBean(clazz);
}
public static <T> T getBean(String name, Class<T> clazz){
return ac.getBean(name, clazz);
}
}
有时我只使用beanutil
类获取bean:
BookMapper bookMapper = BeanUtil.getBean(BookMapper.class);
这很方便,因为我可以得到来自静态方法的豆。
现在的问题是,当我运行集成测试时,我发现bookmapper
使用上述两种方式提取(@Autowired
和beantil
)是不同(有时它们是相同的,我无法再现问题)。为什么?它不应该发生,因为bookmapper
是singleton
。有可能原因吗?
I have a spring-boot project that contains a BookMapper
bean:
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BookMapper {
// some CRUD methods here...
}
The bean is created by mybatis
, and it's a Singleton
. Usually, I use the bean with @Autowired
:
@Service
public BookService {
@Autowired
private BookMapper bookMapper;
}
I also have a file like this:
@Component
public class BeanUtil implements ApplicationContextAware {
private static ApplicationContext ac;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ac = applicationContext;
}
public static <T> T getBean(Class<T> clazz){
return ac.getBean(clazz);
}
public static <T> T getBean(String name, Class<T> clazz){
return ac.getBean(name, clazz);
}
}
Sometimes I just fetch the bean using the BeanUtil
class:
BookMapper bookMapper = BeanUtil.getBean(BookMapper.class);
That is convenient because I can get a bean from a static method.
Now the problem is, when I run integration tests, I find that BookMapper
fetched using the above two ways (@Autowired
and BeanUtil
) are sometimes different (and they are sometimes the same, I cannot reproduce the problem). Why? It shouldn't happen because BookMapper
is a Singleton
. Is there a possible reason for it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我有类似的问题。
在我的情况下,Beens是多次创建的,因为几个测试具有不同的配置(不同的配置文件,或用模拟的bean覆盖Bean),因此运行所有集成测试启动了多次弹簧上下文,
您拥有
static ApplicationContext AC
inbeanutil
因此,春季可能会创建不同的beanutil
durring创建新上下文,但它们存储了applicationContext
这些上下文之间的奇特互动I have kind of similar problem.
In my case beens are created multiple times because couple of tests have different configuration (different profiles, or overriding bean with mock) so when running all integration tests spring context is started multiple times
You have
static ApplicationContext ac
inBeanUtil
so spring may creates differentBeanUtil
durring creating new context but they storeApplicationContext
instatic
so there may be some wierd interactions between those contexts在调试很长时间后,我发现了原因。我在测试中使用
@mockbean
。在这种情况下,spring-test
将创建第二个applicationContext
,它与我的问题代码中beanutil
使用的不同。当您有两个上下文时,每个班级都会有两个豆子。我不是
@mockbean
的沉重用户,所以我暂时将其删除,然后问题消失了。After debugging for a long time, I found out the reason. I use
@MockBean
in my test. In this case,spring-test
will create a secondApplicationContext
, which is different from the one used byBeanUtil
in my question's code. When you have two contexts, you will have two beans for each class.I'm not a heavy user of
@MockBean
, so I just remove it for now, then the problem disappeared.