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

Spring注入bean的四種方式總結(jié)

 更新時間:2025年11月27日 09:11:46   作者:K***6589  
我們談到Spring的時候一定會提到IOC容器、DI依賴注入,Spring通過將一個個類標注為Bean的方法注入到IOC容器中,達到了控制反轉(zhuǎn)的效果,Spring幫我們實現(xiàn)了一種通過注解來實現(xiàn)注入的方法,所以本文為大家介紹了Spring注入bean的四種方式,需要的朋友可以參考下

一提到 Spring,大家最先想到的是啥?是 AOPIOC 的兩大特性?是 SpringBean 的初始化流程?還是基于 SpringSpring Cloud 全家桶呢?

今天我們就從 SpringIOC 特性入手,聊一聊 Spring 中把 Bean 注入 Spring 容器的幾種方式。

我們先來簡單了解下 IOC 的概念:IOC控制反轉(zhuǎn),也稱為 依賴注入,是指將 對象的創(chuàng)建 或者 依賴關系的引用 從具體的對象控制轉(zhuǎn)為框架或者 IOC 容器來完成,也就是依賴對象的獲得被反轉(zhuǎn)了。

可以簡單理解為原來由我們來創(chuàng)建對象,現(xiàn)在由 Spring 來創(chuàng)建并控制對象。

一、xml 方式

依稀記得最早接觸 Spring 的時候,用的還是 SSH 框架,不知道大家對這個還有印象嗎?所有的 bean 的注入得依靠 xml 文件來完成。

它的注入方式分為:set 方法注入、構(gòu)造方法注入、字段注入,而注入類型分為值類型注入(8 種基本數(shù)據(jù)類型)和引用類型注入(將依賴對象注入)。

以下是 set 方法注入的簡單示例:

<bean name="teacher" class="org.springframework.demo.model.Teacher">
    <property name="name" value="張老師"></property>
</bean>

對應的實體類代碼:

public class Teacher {
	private String name;
	
	public void setName(String name) {
		this.name = name;
	}
}

xml方式存在的缺點如下:

  1. xml 文件配置起來比較麻煩,既要維護代碼又要維護配置文件,開發(fā)效率低;
  2. 項目中配置文件過多,維護起來比較困難;
  3. 程序編譯期間無法對配置項的正確性進行驗證,只能在運行期發(fā)現(xiàn)并且出錯之后不易排查;
  4. 解析 xml 時,無論是將 xml 一次性裝進內(nèi)存,還是一行一行解析,都會占用內(nèi)存資源,影響性能。

二、注解方式

隨著 Spring 的發(fā)展,Spring 2.5 開始出現(xiàn)了一系列注解,除了我們經(jīng)常使用的@Controller、@Service@Repository、@Component 之外,還有一些比較常用的方式,接下來我們簡單了解下。

@Configuration + @Bean

當我們需要引入第三方的 jar 包時,可以用 @Bean 注解來標注,同時需要搭配 @Configuration 來使用。

  • @Configuration 用來聲明一個配置類,可以理解為 xml<beans> 標簽
  • @Bean 用來聲明一個 bean,將其加入到 Spring 容器中,可以理解為 xml<bean> 標簽

簡單樣例:將 RedisTemplate 注入 Spring

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        ......
        return redisTemplate;
    }
}

@Import

我們在翻看 Spring 源碼的過程中,經(jīng)常會看到 @Import 注解,它也可以用來將第三方 jar 包注入 Spring,但是它只可以作用在類上。

例如在注解 EnableSpringConfigured 上就包含了 @Import 注解,用于將 SpringConfiguredConfiguration 配置文件加載進 Spring 容器。

@Import(SpringConfiguredConfiguration.class)
public @interface EnableSpringConfigured {}

@Importvalue 值是一個數(shù)組,一個一個注入比較繁瑣,因此我們可以搭配 ImportSelector 接口來使用,用法如下:

@Configuration
@Import(MyImportSelector.class)
public class MyConfig {}

public class MyImportSelector implements ImportSelector {
 @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"org.springframework.demo.model.Teacher","org.springframework.demo.model.Student"};
    }
}

其中 selectImports 方法返回的數(shù)組就會通過 @Import 注解注入到 Spring 容器中。

無獨有偶,ImportBeanDefinitionRegistrar 接口也為我們提供了注入 bean 的方法。

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    ......
}

我們點擊 AspectJAutoProxyRegistrar 類,發(fā)現(xiàn)它實現(xiàn)了 ImportBeanDefinitionRegistrar 接口,它的 registerBeanDefinitions 方法便是注入 bean 的過程,可以參考下。

如果覺得源代碼比較難懂,可以看一下我們自定義的類:

@Configuration
@Import(value = {MyImportBeanDefinitionRegistrar.class})
public class MyConfig {}

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                                        BeanDefinitionRegistry registry) {
            RootBeanDefinition tDefinition = new RootBeanDefinition(Teacher.class);
            // 注冊 Bean,并指定bean的名稱和類型
            registry.registerBeanDefinition("teacher", tDefinition);
        }
    }
}

這樣我們就把 Teacher 類注入到 Spring 容器中了。

三、FactoryBean

提到 FactoryBean,就不得不與 BeanFactory 比較一番。

  • BeanFactory : 是 Factory, IOC 容器或者對象工廠,所有的 Bean 都由它進行管理
  • FactoryBean : 是 Bean ,是一個能產(chǎn)生或者修飾對象生成的工廠 Bean,實現(xiàn)與工廠模式和修飾器模式類似

那么 FactoryBean 是如何實現(xiàn) bean 注入的呢?

先定義實現(xiàn)了 FactoryBean 接口的類

public class TeacherFactoryBean implements FactoryBean<Teacher> {

	 /**
	  * 返回此工廠管理的對象實例
	  **/
	 @Override
	 public Teacher getObject() throws Exception {
	  	return new Teacher();
	 }
	
	 /**
	  * 返回此 FactoryBean 創(chuàng)建的對象的類型
	  **/
	 @Override
	 public Class<?> getObjectType() {
	  	return Teacher.class;
	 }

}

然后通過 @Configuration + @Bean 的方式將 TeacherFactoryBean 加入到容器中

@Configuration
public class MyConfig {
	 @Bean
	 public TeacherFactoryBean teacherFactoryBean(){
	  	return new TeacherFactoryBean();
	 }
}

注意:我們沒有向容器中注入 Teacher,而是直接注入的 TeacherFactoryBean,然后從容器中拿 Teacher 這個類型的 bean,成功運行。

四、BDRegistryPostProcessor

看到這個接口,不知道對于翻看過 Spring 源碼的你來說熟不熟悉。如果不熟悉的話請往下看,要是熟悉的話就再看一遍吧。

源碼

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    // 注冊bean到spring容器中
 	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

@FunctionalInterface
public interface BeanFactoryPostProcessor {
 	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

BeanFactoryPostProcessor 接口是 BeanFactory 的后置處理器,方法postProcessBeanFactorybean 的定義進行控制。今天我們重點來看看 postProcessBeanDefinitionRegistry 方法:它的參數(shù)是 BeanDefinitionRegistry,顧名思義就是與 BeanDefinition 注冊相關的。

通過觀察該類,我們發(fā)現(xiàn)它里邊包含了 registerBeanDefinition 方法,這個不就是我們想要的嗎?為了能更好的使用該接口來達到注入 bean 的目的,我們先來看看 Spring 是如何操作此接口的。

看下 invokeBeanFactoryPostProcessors 方法,會發(fā)現(xiàn)沒有實現(xiàn) PriorityOrdered和Orderedbean(這種跟我們自定義的實現(xiàn)類有關)會執(zhí)行以下代碼。

while (reiterate) {
    ......
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    ......
}

進入該方法

private static void invokeBeanDefinitionRegistryPostProcessors(
    Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, 
    BeanDefinitionRegistry registry) {

    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}

會發(fā)現(xiàn)實現(xiàn)了 BeanDefinitionRegistryPostProcessor 接口的 bean,其 postProcessBeanDefinitionRegistry 方法會被調(diào)用,也就是說如果我們自定義接口實現(xiàn)該接口,它的 postProcessBeanDefinitionRegistry 方法也會被執(zhí)行。

實戰(zhàn)

話不多說,直接上代碼。自定義接口實現(xiàn)類

public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

	 /**
	  * 初始化過程中先執(zhí)行
	  **/
	 @Override
	 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		  RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Teacher.class);
		  //Teacher 的定義注冊到spring容器中
		  registry.registerBeanDefinition("teacher", rootBeanDefinition);
	 }
	
	 /**
	  * 初始化過程中后執(zhí)行
	  **/
	 @Override
	 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}

啟動類代碼

public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    MyBeanDefinitionRegistryPostProcessor postProcessor = new MyBeanDefinitionRegistryPostProcessor();
    // 將自定義實現(xiàn)類加入 Spring 容器
    context.addBeanFactoryPostProcessor(postProcessor);
    context.refresh();
    Teacher bean = context.getBean(Teacher.class);
    System.out.println(bean);
}

啟動并打印結(jié)果

org.springframework.demo.model.Teacher@2473d930

發(fā)現(xiàn)已經(jīng)注入到 Spring 容器中了。

以上就是我們總結(jié)的幾種將 bean 注入 Spring 容器的方式,趕快行動起來實戰(zhàn)演練一下吧!!

到此這篇關于Spring注入bean的四種方式總結(jié)的文章就介紹到這了,更多相關Spring注入bean內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • SpringBoot集成MongoDB的實現(xiàn)

    SpringBoot集成MongoDB的實現(xiàn)

    本文主要介紹了SpringBoot集成MongoDB的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-01-01
  • 基于Protobuf動態(tài)解析在Java中的應用 包含例子程序

    基于Protobuf動態(tài)解析在Java中的應用 包含例子程序

    下面小編就為大家?guī)硪黄赑rotobuf動態(tài)解析在Java中的應用 包含例子程序。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • SpringBoot整合Docker實現(xiàn)一次構(gòu)建到處運行的操作方法

    SpringBoot整合Docker實現(xiàn)一次構(gòu)建到處運行的操作方法

    本文講解的是 SpringBoot 引入容器化技術(shù) Docker 實現(xiàn)一次構(gòu)建到處運行,包括鏡像構(gòu)建、Docker倉庫搭建使用、Docker倉庫可視化UI等內(nèi)容,需要的朋友可以參考下
    2022-10-10
  • java編程枚舉類型那些事!枚舉類型定義和重寫枚舉的方法

    java編程枚舉類型那些事!枚舉類型定義和重寫枚舉的方法

    本文主要介紹了枚舉類型的有關內(nèi)容,涉及簡單的枚舉類型定義,以及枚舉類型的值在Java中的定義方法,具有一定參考價值,需要的朋友可以了解下。
    2017-10-10
  • 史上最全的java隨機數(shù)生成算法分享

    史上最全的java隨機數(shù)生成算法分享

    這篇文章主要介紹了史上最全的java隨機數(shù)生成算法,我分享一個最全的隨機數(shù)的生成算法,最代碼的找回密碼的隨機數(shù)就是用的這個方法
    2014-01-01
  • 在Spring中配置Quartz的三種方式

    在Spring中配置Quartz的三種方式

    Spring Quartz 是一個任務調(diào)度框架,它允許我們定期執(zhí)行特定的任務,在 Spring 中,我們可以通過多種方式來配置 Quartz,包括使用 ??@Scheduled?? 注解、XML 配置和 Java 配置,本文將介紹如何在 Spring 中使用這三種方式來配置 Quartz,需要的朋友可以參考下
    2025-01-01
  • SpringCloud2020整合Nacos-Bootstrap配置不生效的解決

    SpringCloud2020整合Nacos-Bootstrap配置不生效的解決

    這篇文章主要介紹了SpringCloud2020整合Nacos-Bootstrap配置不生效的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • nacos在liunx系統(tǒng)中啟動成功瀏覽器卻訪問不了的解決方法

    nacos在liunx系統(tǒng)中啟動成功瀏覽器卻訪問不了的解決方法

    在linux下搭建nacos,現(xiàn)在想要啟動,訪問nacos頁面,訪問不了,所以本文小編將給大家介紹nacos在liunx系統(tǒng)中啟動成功,瀏覽器卻訪問不了?全面的解決辦法,需要的朋友可以參考下
    2023-09-09
  • springBoot靜態(tài)資源加載不到,并且配置了也不生效問題及解決

    springBoot靜態(tài)資源加載不到,并且配置了也不生效問題及解決

    這篇文章總結(jié)了一個在Spring Boot 2.6.x版本中,由于路徑匹配策略改變導致靜態(tài)資源無法加載的問題,并提供了解決方案:通過配置類或在配置文件中設置路徑匹配策略為AntPathMatcher,或者直接降級Spring Boot版本
    2025-02-02
  • MyBatis執(zhí)行SQL查詢的完整流程

    MyBatis執(zhí)行SQL查詢的完整流程

    本文詳細介紹了MyBatis SQL執(zhí)行的完整過程,包括核心對象、代碼實現(xiàn)與執(zhí)行鏈路,通過編程式調(diào)用示例和流程圖,展示了從環(huán)境配置、SqlSession創(chuàng)建到結(jié)果獲取的全步驟,需要的朋友可以參考下
    2026-01-01

最新評論

景洪市| 扎囊县| 阜平县| 冀州市| 农安县| 大荔县| 澜沧| 菏泽市| 射洪县| 盘山县| 赞皇县| 高雄县| 临洮县| 改则县| 灵台县| 平利县| 赞皇县| 黄平县| 武汉市| 金平| 岚皋县| 石泉县| 措勤县| 灵川县| 根河市| 织金县| 闵行区| 安岳县| 金平| 新蔡县| 新巴尔虎左旗| 荣昌县| 鄱阳县| 科尔| 双桥区| 洮南市| 偃师市| 汽车| 兰西县| 开江县| 南澳县|