前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ApplicationContext可以同时获取多个Bean吗?

ApplicationContext可以同时获取多个Bean吗?

作者头像
疯狂的KK
修改2023-02-06 18:11:11
9380
修改2023-02-06 18:11:11
举报
文章被收录于专栏:Java项目实战Java项目实战

 在实际场景中提供了N个接口给第三方,常规情况下是不会同时调用的,如果N个接口同时调用,随着接口的数量和业务场景逻辑增加,将会给服务带来很不好的体验,但恰恰业务就是如此,面对同一类型的业务查询场景,我将策略模式应用到此接口上来应对。关于实际设计的demo可参考往期文章炫技?No.

    这个对外接口与以往不同的是,接口调用通过openFeign方式调用,针对此类调用也提醒了注意事项CompletableFuture调用OpenFegin,谁用谁傻,除了业务需求的更改,已经是上线逻辑了,但偶发的出现了返回数据为null的情况,针对业务已经对Integer做了处理,正常的应该是返回0的,且出现null的情况也未能复现,针对代码做出排查。

ApplicationContext可以同时获取多个Bean吗?

其实这个问题不应该这么问,多线程调用的默认Springboot的无状态Bean是线程安全的,一般情况下是不会对Bean的成员变量进行修改的,这个跟修改注解的方法值那个问题是两个问题,context无非是一个map,当在外部进行调用的前提,我所需要的我bean是一定已经初始化完成的,我们看下context的内部存储数据:

图片
图片
代码语言:javascript
复制
在这里可以看到已经初始化的bean,或者在beanDefinitionMap中也能看到,
只不过在其实现中是有区别的,比如在SimpleJndiBeanFactory中其getBean方法是一个HashMap,
而在DefaultListableBeanFactory中则是ConcurrentHashMap,
所以不管是哪种类型,在map中同时获取bean是没有问题的,即便是在多线程场景下。

 考虑到版本和镜像初始化问题,如果需要可以在bean初始化完成之后进行指定bean的初始化。

1.实现ApplicationListener接口

Bean在初始化完成后会执行onApplicationEvent方法

代码语言:javascript
复制

@Component
public class LazyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    public LazyApplicationListener() {
        System.out.println("LazyApplicationListener init");
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (event.getApplicationContext().getParent() == null) {
            System.out.println("LazyApplicationListener onApplicationEvent");
        }
    }
}

2.实现InitializingBean接口

Bean在初始化完成后会执行afterPropertiesSet()

代码语言:javascript
复制

@Component
public class LazyInitializingBean implements InitializingBean {
    public LazyInitializingBean() {
        System.out.println("LazyInitializingBean init");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("LazyInitializingBean afterPropertiesSet");
    }
}

3.使用@PostConstruct注解

代码语言:javascript
复制

@Component
public class LazyPostConstructAnnotation {
    public LazyPostConstructAnnotation() {
        System.out.println("LazyPostConstructAnnotation constructor");
    }

    @PostConstruct
    public void init(){
        System.out.println("LazyPostConstructAnnotation init");
    }
}
2023-01-09 17:29:55.588  INFO 5884 --- [main] o.s.web.context.ContextLoader            : 
Root WebApplicationContext: initialization completed in 2489 ms
图片
图片

那么为何为null?

SQL语句不能保证100%为null,原sql如下

代码语言:javascript
复制
 <select id="task" resultType="java.lang.Integer">
        select  count(*)  from  (select  id from xxx tri
                                 where xxx
                                   xxx
                                   xxx
                                 GROUP BY xxx) a
   </select>

count(字段名):返回select语句检索的行中字段名的值不为null的数量,结果是BIGINT值;

count(*):统计结果中会包含值为null的行数;

count(常量):count(*)、count(常量):表示的是直接查询符合条件的数据库表的行数。而count(列名)表示的是查询符合条件的列的值不为null的行数;

原因猜测 

    如果确实为null可手动处理Integer值。但其实并没有再次复现此问题,我其实怀疑是因为在这个期间我某个SQL当时写错了,构建完没改的情况导致在一个接口同时调用时报错,从而返回了null。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-01-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 赵KK日常技术记录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档