SpringBoot引入第三方jar的Bean的三種方式


在SpringBoot的大環境下,基本上很少使用之前的xml配置Bean,主要是因為這種方式不好維護而且也不夠方便。 因此本篇博文也不再介紹Spring中通過xml來聲明bean的使用方式。

一、注解裝配Bean

1、使用@Component等派生注解

只要在類上加類上加 @Component 注解即可,該注解只要被掃描到就會注入到spring的bean容器中。

@Component
public class AnoDemoBean {
}

當然不只是@Component注解可以聲明Bean,還有如:@Repository@Service@Controller 等常用注解同樣可以。

如果去看這些注解,就發現這些注解上本身就有加 @Component 注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component   //可以看到@Service注解上有添加@Component,  @Repository和@Controller也一樣。        
public @interface Service {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

這系列注解的出現,給我們帶來了極大的便利。我們不需要像以前那樣在bean.xml文件中配置bean了,現在只用在類上加上相關注解,就能輕松完成bean的定義。

這四種注解在功能上其實沒有特別的區別,不過在業界有個不成文的約定:

  • Controller 一般用在控制層
  • Service 一般用在業務層
  • Repository 一般用在數據層
  • Component 一般用在公共組件上

2、@Bean定義方式

這種方式,主要是結合Configuration來定義bean,首先是聲明一個配置類,而后再配置類中,經過返回bean對象的方法形式來聲明bean,通常使用姿式以下

@Data
public class ConfigDemoBean {
}

@Configuration
public class BeanLoadConfig {
    @Bean
    public ConfigDemoBean configDemoBean() {
        return new ConfigDemoBean();
    }
}

須要說明的一點是BeanLoadConfig類自己也被Spring容器看為一個Bean。

3、@Component VS @Bean

1)作用對象不同:@Component 注解作用於類,而 @Bean 注解作用於方法

這樣的特點會讓 @Bean 方式更加靈活。比如當我們引用第三方庫中的類需要裝配到 Spring 容器時,只能通過 @Bean 來實現。

比如

@Configuration
public class WireThirdLibClass {
    @Bean
    public ThirdLibClass getThirdLibClass() {
        //第三方的ThirdLibClass類
        return new ThirdLibClass();
    }
}

再比如

@Bean
public OneService getService(status) {
    case (status)  {
        when 1:
                return new serviceImpl1();
        when 2:
                return new serviceImpl2();
        when 3:
                return new serviceImpl3();
    }
}

這兩點都是@Component無法做到,只能@Bean實現,所以說@Bean更加靈活。

2)@Component通常是通過類路徑掃描來自動裝配到Spring容器中。而@Bean通常我們會在該注解的方法中定義產生這個bean的邏輯。

我們可以加一些@Conditional,@ConditionalOnBean等等一些注解來控制是否聲明該Bean,不會一開始就自動裝配到Spring容器中。

比如

public class MacCondition implements Condition {

   @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment environment = conditionContext.getEnvironment();
        String property = environment.getProperty("os.name");
        if (property.contains("Mac")) {
            log.info("當前操作系統是:Mac OS X");
            return true;
        }
        return false;
    }
}



@Configuration
public class ConditionalConfig {
    /**
     * 如果MacCondition的實現方法返回true,則注入這個bean
     */
    @Bean("mac")
    @Conditional({MacCondition.class})
    public SystemBean systemMac() {
        log.info("ConditionalConfig方法注入 mac實體");
        return new SystemBean("Mac ios系統","001");
    }
}

上面的例子表示,如果當前操作系統是Mac,才會注入當前Bean。這個也只能 @Bean 注解才能實現。

總結:@Component和@Bean都是用來注冊Bean並裝配到Spring容器中,但是Bean比Component的自定義性更強。可以實現一些Component實現不了的自定義加載類。


二、引入外部jar包的Bean

如果上面的注解加在當前項目中那么當SpingBoot主類啟動的時候,@SpringBootApplication注解會默認去掃描的本包它的子包的所有需要裝配的類,自動裝配到spring的bean容器中。

但是如果你提供了一個Jar包供第三方用戶使用,那么你這個jar包中的Bean,能被第三方加載么?

這就要看你當前項目的包名和你你引用的第三方Jar包的包名了。

如果你當前項目本包的地址是com.jincou 而你引用的第三方Jar的本包是 com.third,那么也就是第三方Jar的Bean無法被掃描到,所以也就無法注入到Spring容器中。

比如這里有個第三方的Bean。要如何做才能被掃描注入到Spring容器中呢。

package com.third.bean;

import org.springframework.stereotype.Component;

/**
 * @Description: 這個bean作為第三方bean 給依賴該jar包的項目使用
 */
@Component
public class ThirdComponentBean {
    private String type = "第三方ThirdComponent注解生成bean實體";
}

1、@ComponentScan

很簡單,既然@SpringBootApplication注解默認掃描只是當前項目的本包它的子包,那就想辦法讓它掃描第三方jar的包就好了。

/**
 * @Description: Springboot 啟動類
 */
@ComponentScan(basePackages ={"com.third.bean"})
@SpringBootApplication()
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

@ComponentScan主要就是定義掃描的路徑從中找出標識了需要裝配的類自動裝配到spring的bean容器中。

需要裝配的類也就是上面加了@Controller,@Service,@Repository,@Component,@Configuration等等的注解的Bean到IOC容器中。

這里不一定要加在啟動類上,你可以加在加在裝配的類上,但建議加在啟動類上,比較直觀,后期如果要改動或者去除也比較好找。

2、@Import注解

@ComponentScan是掃描整個包,但其實你可能只需注入一個或者幾個指定的Bean,那我們可以考慮用 @Import 注解

@Import(value= com.third.bean.ThirdComponentBean.class)
@SpringBootApplication()
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

這樣做同樣也會成功的將ThirdComponentBean對象注入到Spring的bean容器中。

3、spring.factories

上面兩種注入方式都有個很明顯缺點,就是如果我需要引用外部jar包的Bean的時候,都需要在當前項目配置 @ComponentScan 或者 @Import 去掃描才能注入當前Bean,這樣顯然不夠友好。

可不可以當前項目什么都不做就可以直接引用第三方jar的Bean呢?

當然可以。

我們只需要在將配置放在第三方jar指定的文件中即可,使用者會自動加載,從而避免的代碼的侵入

  • 在資源目錄下新建目錄 META-INF
  • 在 META-INF 目錄下新建文件 spring.factories
  • 在文件中添加下面配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.third.bean.ConfigurationBean

完整項目

相關demo項目已經放到gitHub上,這里創建了兩個項目 create-beanthird-bean 同時third-bean當作第三方jar包被create-bean引用,可以在這個demo上進行相關測試。

GitHub項目源碼: https://github.com/yudiandemingzi/spring-boot-study


聲明: 公眾號如需轉載該篇文章,發表文章的頭部一定要 告知是轉至公眾號: 后端元宇宙。同時也可以問本人要markdown原稿和原圖片。其它情況一律禁止轉載!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM