问答

spring注入怎么样设置默认值?

作者:admin 2021-06-27 我要评论

可能标题不准确,描述一下问题: 有这么一个接口: public interface InterceptorPredicate { default boolean allowed(HttpServletRequest request) { return t...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

可能标题不准确,描述一下问题:

有这么一个接口:

public interface InterceptorPredicate {
    default boolean allowed(HttpServletRequest request) {
        return true;
    }
}

然后有个拦截器:

public class MyInterceptor implements HandlerInterceptor {
    private InterceptorPredicate predicate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (predicate.allowed(request)) {
            do something...
        }
        return true;
    }

    public MyInterceptor(InterceptorPredicate predicate) {
        this.predicate = predicate;
    }
}

我要怎么样做到说如果外部有实现了InterceptorPredicate的bean,那么就用外部的,否则用默认的实现类?

就像DataSource可以用spring自己默认的,也可以用自定义的一样。

###

这个可以用 FactoryBean 来解决
业务类依赖 FactoryBean, FactoryBean 里面的 getObject 方法根据实际情况构造需要的对象 (例如你可以在那里访问 ApplicationContext, 能捞得到对象就返回捞到的对象, 否则则自己 new 一个)

另外实际上 MyBatis 也用到了这个 (SqlSessionFactoryBean等等等)

###

FactoryBean去定义具体获取方式不同,其实也有Spring提供类似的机制,可以完成这个获取方式,即有自定义的用自定义,没有的话,使用默认的
比如:

@ConditionalOnMissingBean

@ConditionalOnMissingBean这个注解,你在配置你的默认实现时,给它上面加一个

@Bean
@ConditionalOnMissingBean(InterceptorPredicate.class)
public InterceptorPredicate defaultPre(){
    return new YourDefaultPredicate();
}

这样如果配置之后,如果别人有配置了InterceptorPredicate的实现,那你这个默认的实现自动失效了,然后你在你的MyInterceptor里可以直接@Autowired即可

@Component
public class MyInterceptor implements HandlerInterceptor {
    @Autowired
    private InterceptorPredicate predicate;
    
}

其实这种做法,官方里也很常用,尤其在一些autoconfigure,比如redisTemplate
image.png

亦或者mongoTemplate

image.png

ObjectProvider

从该接口的注释就可以看得出,它就是你想要的,尤其是optionality,选择性,意味着你可以选择你Bean的实现
image.png

其中的方法getIfAvailable,从名字你就可以看出来,如果Bean存在就返回
image.png

不说其他,我们看看其他autoconfigure包里是怎么使用的,你就明白了
image.png

所以这样你的MyInterceptor就好配置啦

@Bean
public HandlerInterceptor myInterceptor(ObjectProvider<InterceptorPredicate> predicateProvider){
    InterceptorPredicate predicate = predicateProvider.getIfAvailable();
    if(predicate == null) {
        predicate = new YourDefaultPredicate();
    }
    return new MyInterceptor(predicate);
}

当然我们也可以看到MyInterceptor还有一个重载的方法,传入一个默认的Supplier
image.png

所以我们也可以这样写

@Bean
public HandlerInterceptor myInterceptor(ObjectProvider<InterceptorPredicate> predicateProvider){
    InterceptorPredicate predicate = predicateProvider.getIfAvailable(YourDefaultPredicate::new);
    return new MyInterceptor(predicate);
}

如果只是简单的为空默认替换,其实上面两种基本都够用了,如果还有一些额外的不只是判空替换规则的话,你就还需要@Conditional注解了,去定制你的bean注入的条件

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • spring注入怎么样设置默认值?

    spring注入怎么样设置默认值?

  • elementUI 树状图 点击子节点获取父节

    elementUI 树状图 点击子节点获取父节

  • Select选择器选择label时,如何实现树

    Select选择器选择label时,如何实现树

  • element ui Multiple Select 抖动

    element ui Multiple Select 抖动

腾讯云代理商
海外云服务器