最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring如何重寫內(nèi)置Bean(Controller、Service等)

 更新時間:2025年01月06日 09:32:17   作者:catoop  
本文介紹了在Spring Boot工程中處理外部JAR包中Controller方法重寫的需求,通過PostProcessor方式和自定義注解@ExcludeBean兩種方法,解決了在不修改源代碼的情況下重寫接口的問題

Spring重寫內(nèi)置Bean(Controller、Service等)

場景

  • svc1.jar 中有一個 TestController 類,當(dāng)前源代碼工程 demo 依賴了這個 svc1.jar。
  • 當(dāng)前 demo 工程啟動正常,TestController 被初始化,TestController 中提供的接口 /svc1/test1、/svc1/test2、/svc1/test3 均可以正常訪問。
  • 因接口 /svc1/test2 對應(yīng)的方法中邏輯處理不滿足需求,需要對這個方法進行重寫處理。
  • 該接口在 svc1.jar 包,不能直接修改源代碼。

處理方式一(簡單處理)

主要思路是在 Spring 注冊 Bean 之后進行 PostProcessor 時,將已經(jīng)注冊的 svc1.jar 中的 TestController 從上下文中刪除。

使我們新創(chuàng)建的繼承 TestController 的重寫類能被正常加載實例化,而不出現(xiàn) PathMapping 重復(fù)的報錯沖突。

主要代碼如下:

/**
 * 排除容器中的Bean
 * 
 * @author 單紅宇
 * @since 2024/11/28 13:14
 */
@Slf4j
@Configuration
public class ExcludeComponentConfiguration implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        registry.removeBeanDefinition(getDefaultBeanName(FileController.class));
        registry.removeBeanDefinition(getDefaultBeanName(UserController.class));
    }

    /**
     * 根據(jù)類 class 獲取 spring 默認的 beanName
     *
     * @param clazz clazz
     * @return String
     */
    private String getDefaultBeanName(Class<?> clazz) {
        // 測試內(nèi)部類 AutowireUtils.ObjectFactoryDelegatingInvocationHandler 的默認 BeanName
        // StringUtils.uncapitalizeAsProperty(ClassUtils.getShortName(AutowireUtils.ObjectFactoryDelegatingInvocationHandler.class.getName()))
        // spring 6.0 之前使用 StringUtils.uncapitalize()
        return org.springframework.util.StringUtils.uncapitalizeAsProperty(ClassUtils.getShortName(clazz.getName()));
    }
}
/**
 * 重寫FileController類
 * 
 * @author 單紅宇
 * @since 2024/11/28 12:03
 */
@RestController //該注解必須要有,Mapping那些注解不需要
public class OverrideFileController extends FileController {

    @Override
    public void fileDownload(@RequestParam("fileId") Long fileId,
                             @RequestParam("isInline") Integer isInline,
                             HttpServletResponse response, HttpServletRequest request) {
        System.out.println("override filedownload...");
    }

}

處理方式二(自定義注解)

我們可以自定義一個注解 @ExcludeBean,然后使用該注解來很方便的在任何地方來排除需要排除的類。

1、自定義注解

/** 
 * 自定義注解,用來排除原本會在spring上下文中的bean。
 * 一般用于刪除一個不可以修改的Bean,然后自定義一個類繼承原有類然后重寫特定的方法取代原來的類
 * 
 * @author 單紅宇
 * @since 2024/12/5 9:36
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ExcludeBean {
    Class<?>[] clazz() default {};
    String[] name() default {};
}

2、自動配置類

/**
 * 排除 Spring Bean 自動配置類
 * @author 單紅宇
 * @since 2024/12/5 9:13
 */
@AutoConfiguration
public class ExcludeBeanAutoConfiguration implements BeanDefinitionRegistryPostProcessor {
    
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // not implemented
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        if (beanFactory instanceof BeanDefinitionRegistry bdr) {
            Arrays.stream(beanFactory.getBeanNamesForAnnotation(ExcludeBean.class))
                    .map(item -> beanFactory.findAnnotationOnBean(item, ExcludeBean.class, false)).filter(Objects::nonNull)
                    .flatMap(item -> Stream.concat(Arrays.stream(item.name()),
                            Arrays.stream(item.clazz()).map(cls -> 
                                    org.springframework.util.StringUtils.uncapitalizeAsProperty(ClassUtils.getShortName(cls.getName())))))
                    .distinct()
                    .forEach(bdr::removeBeanDefinition);
        }
    }

}

3、配置自動配置

@AutoConfiguration 自動配置注解啟用的方法詳見文章: SpringBoot 自動配置 @AutoConfiguration 在 2.7 版本新增

4、注解使用示例

我們來重寫一個 Controller 的方法,主要應(yīng)用場景是:目標(biāo) Controller 是通過 jar 包依賴過來的,并且我們需要重寫其中的一個方法邏輯。

/**
 * 重寫 Controller 類 TestApi 中的特定方法
 * 
 * @author 單紅宇
 * @since 2024/11/28 9:06
 */
@ExcludeBean(clazz = TestApi.class)
@RestController
public class OverrideTestApi extends TestApi {

    /**
     * 重寫 Hello 方法
     *
     * @return String
     */
    @Override
    public String hello() {
        return "Hello, Override!";
    }

}

補充

如果是基于一個接口然后有多個實現(xiàn)類的多實例場景,使用的地方是基于接口注入的。

也可以使用 @Primary 注解來修飾特定的類。

但是對于如 Controller 以及其他沒有定義并通過接口注入方式的可能就要使用我們本文的方法了。

總結(jié)

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

相關(guān)文章

  • Java開發(fā)中StepBuilder模式詳解

    Java開發(fā)中StepBuilder模式詳解

    Step builder多階段步驟構(gòu)造器模式是一種對象創(chuàng)建軟件設(shè)計模式,與傳統(tǒng)構(gòu)建器模式進行比較時,步驟構(gòu)建器模式提供了一些簡潔的好處,這篇文章主要介紹了Java開發(fā)中StepBuilder模式的相關(guān)資料,需要的朋友可以參考下
    2026-01-01
  • 詳解SpringBoot應(yīng)用服務(wù)啟動與安全終止

    詳解SpringBoot應(yīng)用服務(wù)啟動與安全終止

    這篇文章主要介紹了SpringBoot應(yīng)用服務(wù)啟動與安全終止,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 詳解RocketMQ 消費端如何監(jiān)聽消息

    詳解RocketMQ 消費端如何監(jiān)聽消息

    這篇文章主要為大家介紹了RocketMQ 消費端如何監(jiān)聽消息示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • JSON復(fù)雜數(shù)據(jù)處理之Json樹形結(jié)構(gòu)數(shù)據(jù)轉(zhuǎn)Java對象并存儲到數(shù)據(jù)庫的實現(xiàn)

    JSON復(fù)雜數(shù)據(jù)處理之Json樹形結(jié)構(gòu)數(shù)據(jù)轉(zhuǎn)Java對象并存儲到數(shù)據(jù)庫的實現(xiàn)

    這篇文章主要介紹了JSON復(fù)雜數(shù)據(jù)處理之Json樹形結(jié)構(gòu)數(shù)據(jù)轉(zhuǎn)Java對象并存儲到數(shù)據(jù)庫的實現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2016-03-03
  • Java運算符從見過到掌握上

    Java運算符從見過到掌握上

    計算機的最基本用途之一就是執(zhí)行數(shù)學(xué)運算,作為一門計算機語言,Java也提供了一套豐富的運算符來操縱變量,本篇對大家的學(xué)習(xí)或工作具有一定的價值,需要的朋友可以參考下
    2021-09-09
  • java遞歸算法的實例詳解

    java遞歸算法的實例詳解

    在本篇文章里小編給大家整理了關(guān)于java遞歸算法的實例內(nèi)容,以及相關(guān)知識點總結(jié),需要的朋友們可以學(xué)習(xí)下。
    2020-02-02
  • java 啟動exe程序,傳遞參數(shù)和獲取參數(shù)操作

    java 啟動exe程序,傳遞參數(shù)和獲取參數(shù)操作

    這篇文章主要介紹了java 啟動exe程序,傳遞參數(shù)和獲取參數(shù)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • SpringBoot中循環(huán)依賴問題的原理與解決方案

    SpringBoot中循環(huán)依賴問題的原理與解決方案

    在Spring Boot開發(fā)中,依賴注入(DI)是核心特性之一,本文將通過一個實際錯誤案例,深入分析Spring Boot循環(huán)依賴的成因、解決方案,并提供最佳實踐建議,希望對大家有所幫助
    2025-07-07
  • 基于Spring boot @Value 注解注入屬性值的操作方法

    基于Spring boot @Value 注解注入屬性值的操作方法

    這篇文章主要介紹了結(jié)合SpEL使用@Value-基于配置文件或非配置的文件的值注入-Spring Boot的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • java中volatile不能保證線程安全(實例講解)

    java中volatile不能保證線程安全(實例講解)

    下面小編就為大家?guī)硪黄猨ava中volatile不能保證線程安全(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09

最新評論

紫阳县| 时尚| 吴川市| 宝丰县| 库尔勒市| 岐山县| 双峰县| 加查县| 平顶山市| 崇左市| 垦利县| 绩溪县| 明溪县| 修文县| 莆田市| 沈阳市| 台东市| 铜山县| 阿克| 芮城县| 和静县| 普安县| 诸暨市| 张家口市| 阿克陶县| 合水县| 宜兰市| 秦皇岛市| 乌兰浩特市| 曲阳县| 资阳市| 罗源县| 岳池县| 凤庆县| 庄浪县| 惠安县| 灵台县| 昌邑市| 万源市| 三亚市| 洛川县|