为什么在春季两次创建单身豆?

发布于 2025-01-24 19:30:37 字数 1465 浏览 3 评论 0原文

我有一个弹簧启动项目,其中包含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使用上述两种方式提取(@Autowiredbeantil)是不同(有时它们是相同的,我无法再现问题)。为什么?它不应该发生,因为bookmappersingleton。有可能原因吗?

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无远思近则忧 2025-01-31 19:30:37

我有类似的问题。

在我的情况下,Beens是多次创建的,因为几个测试具有不同的配置(不同的配置文件,或用模拟的bean覆盖Bean),因此运行所有集成测试启动了多次弹簧上下文,

您拥有static ApplicationContext AC in beanutil因此,春季可能会创建不同的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 in BeanUtil so spring may creates different BeanUtil durring creating new context but they store ApplicationContext in static so there may be some wierd interactions between those contexts

疯狂的代价 2025-01-31 19:30:37

在调试很长时间后,我发现了原因。我在测试中使用@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 second ApplicationContext, which is different from the one used by BeanUtil 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文