springboot加載注入bean的幾種方式
在SpringBoot的大環(huán)境下,基本上很少使用之前的xml配置Bean,主要是因為這種方式不好維護而且也不夠方便。
springboto注入bean主要采用下圖幾種方式,分為本地服務工程注解聲明的bean和外部依賴包中的bean。

一、 springboot裝配本地服務工程中的bean
1、注解裝配Bean
1、使用Component,Service,Controller,Repository等派生注解
只要在類上加類上加 @Component 注解即可,該注解只要被掃描到就會注入到spring的bean容器中。
@Component
public class AnoDemoBean {
}當然不只是@Component注解可以聲明Bean,還有如:@Repository、@Service、@Controller 等常用注解同樣可以。
如果去看這些注解,就發(fā)現(xiàn)這些注解上本身就有加 @Component 注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component //可以看到@Service注解上有添加@Component, @Repository和@Controller也一樣。
public @interface Service {
@AliasFor(
annotation = Component.class
)
String value() default "";
}
這系列注解的出現(xiàn),給我們帶來了極大的便利。我們不需要像以前那樣在bean.xml文件中配置bean了,現(xiàn)在只用在類上加上相關(guān)注解,就能輕松完成bean的定義。
這四種注解在功能上其實沒有特別的區(qū)別,不過在業(yè)界有個不成文的約定:
- Controller 一般用在控制層
- Service 一般用在業(yè)務層
- Repository 一般用在數(shù)據(jù)層
- Component 一般用在公共組件上
2、@Bean定義方式
這種方式,主要是結(jié)合Configuration來定義bean,首先是聲明一個配置類,而后再配置類中,經(jīng)過返回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 來實現(xiàn)。
比如
@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實現(xiàn),所以說@Bean更加靈活。
2)@Component通常是通過類路徑掃描來自動裝配到Spring容器中。而@Bean通常我們會在該注解的方法中定義產(chǎn)生這個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("當前操作系統(tǒng)是:Mac OS X");
return true;
}
return false;
}
}
@Configuration
public class ConditionalConfig {
/**
* 如果MacCondition的實現(xiàn)方法返回true,則注入這個bean
*/
@Bean("mac")
@Conditional({MacCondition.class})
public SystemBean systemMac() {
log.info("ConditionalConfig方法注入 mac實體");
return new SystemBean("Mac ios系統(tǒng)","001");
}
}
上面的例子表示,如果當前操作系統(tǒng)是Mac,才會注入當前Bean。這個也只能 @Bean 注解才能實現(xiàn)。
總結(jié):@Component和@Bean都是用來注冊Bean并裝配到Spring容器中,但是Bean比Component的自定義性更強。可以實現(xiàn)一些Component實現(xiàn)不了的自定義加載類。
二、springboot裝配依賴包中的bean
當SpingBoot主類啟動的時候,@SpringBootApplication注解會默認去掃描的自己所在包路徑和它的子包路徑下的所有需要裝配的類,自動裝配到spring的bean容器中。
但是如果你提供了一個Jar包供第三方用戶使用,那么你這個jar包中的Bean,能被第三方加載么?
這就要看你當前項目的包名和你引用的第三方Jar包的包名是否一致了?如果一致,第三方依賴包中的bean可以直接加載,如果不一致,則無法加載第三方依賴中的bean。
例如,如果你當前項目本包的地址是com.jincou,而你引用的第三方Jar的本包也是 com.jincou,那么第三方Jar的Bean就可以被掃描到并注入到spring的容器中。如果你當前項目本包的地址是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文件中配置bean
上面兩種注入方式都有個很明顯缺點,就是如果我需要引用外部jar包的Bean的時候,都需要在當前項目配置 @ComponentScan 或者 @Import 去掃描才能注入當前Bean,這樣顯然不夠友好。
可不可以當前項目什么都不做就可以直接引用第三方jar的Bean呢?
當然可以。
我們只需要在將配置放在第三方jar指定的文件中即可,使用者會自動加載,從而避免的代碼的侵入
在資源目錄下新建目錄 META-INF
在 META-INF 目錄下新建文件 spring.factories
在文件中添加下面配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.third.bean.ConfigurationBean
到此這篇關(guān)于springboot加載注入bean的幾種方式的文章就介紹到這了,更多相關(guān)springboot加載注入bean內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot多模塊多環(huán)境配置文件問題(動態(tài)配置生產(chǎn)和開發(fā)環(huán)境)
這篇文章主要介紹了springboot多模塊多環(huán)境配置文件問題(動態(tài)配置生產(chǎn)和開發(fā)環(huán)境),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-04-04
java實戰(zhàn)技巧之if-else代碼優(yōu)化技巧大全
代碼中如果if-else比較多,閱讀起來比較困難,維護起來也比較困難,很容易出bug,下面這篇文章主要給大家介紹了關(guān)于java實戰(zhàn)技巧之if-else代碼優(yōu)化技巧的相關(guān)資料,需要的朋友可以參考下2022-02-02
詳解spring cloud分布式整合zipkin的鏈路跟蹤
這篇文章主要介紹了詳解spring cloud分布式整合zipkin的鏈路跟蹤,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07
關(guān)于SpringBoot整合RabbitMQ實現(xiàn)死信隊列
這篇文章主要介紹了關(guān)于SpringBoot整合RabbitMQ實現(xiàn)死信隊列,死信隊列實際上就是一個普通的隊列,只是這個隊列跟死信交換機進行了綁定,用來存放死信而已,需要的朋友可以參考下2023-05-05

