欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring覆蓋容器中Bean的注解如何實(shí)現(xiàn)@OverrideBean

 更新時(shí)間:2025年01月06日 10:38:45   作者:catoop  
文章介紹了在項(xiàng)目開(kāi)發(fā)中如何通過(guò)偷梁換柱的方式重寫(xiě)Spring容器中的內(nèi)置Bean,并指出了需要注意的兩點(diǎn):1. 對(duì)應(yīng)的Bean應(yīng)基于接口注入;2. 如果不是基于接口注入,可以使用同包名同類名的方式重寫(xiě)(可能存在潛在問(wèn)題,不推薦),文章還強(qiáng)調(diào)了“基于接口編程”的好處

Spring覆蓋容器Bean的注解實(shí)現(xiàn)@OverrideBean

項(xiàng)目開(kāi)發(fā)中,有時(shí)第三方框架會(huì)自動(dòng)注入Bean到Spring容器中,當(dāng)我們有修改對(duì)應(yīng)內(nèi)置Bean實(shí)現(xiàn)的需求時(shí),可以采用偷梁換柱的方式來(lái)重寫(xiě)內(nèi)置的Bean,使用這種方式需要注意以下兩點(diǎn):

  • 1、對(duì)應(yīng)的Bean在其他地方使用時(shí),是基于接口注入的。
  • 2、如果不是基于接口注入的Bean,你可能需要同包名同類名的這種方式重寫(xiě)(可能會(huì)有問(wèn)題,不推薦)。

從以上2點(diǎn)我們還可以得出一個(gè)結(jié)論,那就是“基于接口編程”的好處。

具體實(shí)現(xiàn)參考一下代碼

(代碼片段,僅供參考,根據(jù)實(shí)際使用場(chǎng)景修改后使用):

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 覆蓋Spring容器中的Bean
 *
 * @author shanhy
 * @date 2021/4/25 13:40
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface OverrideBean {

    /**
     * 需要替換的 Bean 的名稱
     *
     * @return
     */
    String value();
    
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * 重寫(xiě)B(tài)ean的配置類
 *
 * @author shanhy
 * @date 2021/4/25 13:41
 */
@Configuration
public class OverrideBeanConfiguration implements BeanDefinitionRegistryPostProcessor, BeanFactoryAware {

    private static final Logger log = LoggerFactory.getLogger(OverrideBeanConfiguration.class);

    private BeanFactory beanFactory;

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        log.debug("searching for classes annotated with @OverrideBean");

        // 自定義 Scanner 掃描 classpath 下的指定注解
        ClassPathOverrideBeanAnnotationScanner scanner = new ClassPathOverrideBeanAnnotationScanner(registry);
        try {
            // 獲取包路徑
            List<String> packages = AutoConfigurationPackages.get(this.beanFactory);

            if (log.isDebugEnabled()) {
                for (String p : packages) {
                    log.debug("Using auto-configuration base package: {}", p);
                }
            }

            // 掃描所有加載的包
            scanner.doScan(StringUtils.toStringArray(packages));
        } catch (IllegalStateException ex) {
            log.debug("could not determine auto-configuration package, automatic OverrideBean scanning disabled.", ex);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    private static class ClassPathOverrideBeanAnnotationScanner extends ClassPathBeanDefinitionScanner {

        ClassPathOverrideBeanAnnotationScanner(BeanDefinitionRegistry registry) {
            super(registry, false);
            // 設(shè)置過(guò)濾器。僅掃描 @OverrideBean
            addIncludeFilter(new AnnotationTypeFilter(OverrideBean.class));
        }

        @Override
        public Set<BeanDefinitionHolder> doScan(String... basePackages) {
            List<String> overrideClassNames = new ArrayList<>();
            // 掃描全部 package 下 annotationClass 指定的 Bean
            Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);

            GenericBeanDefinition definition;
            for (BeanDefinitionHolder holder : beanDefinitions) {
                definition = (GenericBeanDefinition) holder.getBeanDefinition();

                // 獲取類名,并創(chuàng)建 Class 對(duì)象
                String className = definition.getBeanClassName();
                Class<?> clazz = classNameToClass(className);

                // 解析注解上的 value
                OverrideBean annotation = Objects.requireNonNull(clazz).getAnnotation(OverrideBean.class);
                if (annotation == null || annotation.value().length() == 0) {
                    continue;
                }

                // 使用當(dāng)前加載的 @OverrideBean 指定的 Bean 替換 value 里指定名稱的 Bean
                if (Objects.requireNonNull(getRegistry()).containsBeanDefinition(annotation.value())) {
                    getRegistry().removeBeanDefinition(annotation.value());
                    getRegistry().registerBeanDefinition(annotation.value(), definition);
                    overrideClassNames.add(clazz.getName());
                }
            }
            log.info("found override beans: " + overrideClassNames);

            return beanDefinitions;
        }

        // 反射通過(guò) class 名稱獲取 Class 對(duì)象
        private Class<?> classNameToClass(String className) {
            try {
                return Class.forName(className);
            } catch (ClassNotFoundException e) {
                log.error("create instance failed.", e);
            }
            return null;
        }
    }

}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring-cloud Feign 的深入理解

    Spring-cloud Feign 的深入理解

    這篇文章主要介紹了Spring-cloud Feign 的深入理解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • Java實(shí)現(xiàn)簡(jiǎn)單推箱子游戲

    Java實(shí)現(xiàn)簡(jiǎn)單推箱子游戲

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)推箱子游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • Java基于socket服務(wù)實(shí)現(xiàn)UDP協(xié)議的方法

    Java基于socket服務(wù)實(shí)現(xiàn)UDP協(xié)議的方法

    這篇文章主要介紹了Java基于socket服務(wù)實(shí)現(xiàn)UDP協(xié)議的方法,通過(guò)兩個(gè)簡(jiǎn)單實(shí)例分析了java通過(guò)socket實(shí)現(xiàn)UDP發(fā)送與接收的技巧,需要的朋友可以參考下
    2015-05-05
  • Spring Jms 模塊案例講解

    Spring Jms 模塊案例講解

    本文詳細(xì)介紹了Spring-JMS模塊,包括其核心功能和作用,通過(guò)ActiveMQ作為消息代理,提供了一個(gè)基于XML配置的完整示例,幫助開(kāi)發(fā)者快速掌握Spring-JMS的使用方式,感興趣的朋友一起看看吧
    2025-02-02
  • Java多線程連續(xù)打印abc實(shí)現(xiàn)方法詳解

    Java多線程連續(xù)打印abc實(shí)現(xiàn)方法詳解

    這篇文章主要介紹了Java多線程連續(xù)打印abc實(shí)現(xiàn)方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Java?9中List.of()的使用示例及注意事項(xiàng)

    Java?9中List.of()的使用示例及注意事項(xiàng)

    Java 9引入了一個(gè)新的靜態(tài)工廠方法List.of(),用于創(chuàng)建不可變的列表對(duì)象,這篇文章主要介紹了Java?9中List.of()的使用示例及注意事項(xiàng)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-03-03
  • 關(guān)于logBack配置日志文件及編碼配置的問(wèn)題

    關(guān)于logBack配置日志文件及編碼配置的問(wèn)題

    這篇文章主要介紹了logBack配置日志文件及編碼配置的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Spring?@Bean注解深入分析源碼執(zhí)行過(guò)程

    Spring?@Bean注解深入分析源碼執(zhí)行過(guò)程

    隨著SpringBoot的流行,我們現(xiàn)在更多采用基于注解式的配置從而替換掉了基于XML的配置,所以本篇文章我們主要探討基于注解的@Bean以及和其他注解的使用
    2023-01-01
  • Springmvc獲取前臺(tái)請(qǐng)求數(shù)據(jù)過(guò)程解析

    Springmvc獲取前臺(tái)請(qǐng)求數(shù)據(jù)過(guò)程解析

    這篇文章主要介紹了Springmvc獲取前臺(tái)請(qǐng)求數(shù)據(jù)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 詳解feign調(diào)用session丟失解決方案

    詳解feign調(diào)用session丟失解決方案

    這篇文章主要介紹了詳解feign調(diào)用session丟失解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02

最新評(píng)論