Spring?Bean注冊(cè)與注入實(shí)現(xiàn)方法詳解
上接【Spring】spring核心思想——IOC和DI
上篇文章結(jié)尾簡(jiǎn)單介紹了一下使用 XML 注冊(cè) Bean,這篇文章接著介紹一下 XML 注冊(cè) Bean 和使用注解注冊(cè)、注入 Bean
1. 邏輯上的 Bean 注冊(cè)
2. XML 注冊(cè) Bean 到自建的庫(kù)中
上篇文章介紹了使用 XML 三種注冊(cè)的三種方式 (直接注入、構(gòu)造方法注入、set 方法注入),在這里繼續(xù)介紹一下使用工廠方法 和 實(shí)例化工廠注冊(cè) Bean
2.1 工廠方法
工廠方法分為靜態(tài)工廠方法和實(shí)例工廠方法
使用工廠方法注冊(cè)就是調(diào)用靜態(tài)工廠方法注冊(cè) Bean
實(shí)例化工廠注冊(cè)就是調(diào)用實(shí)例工廠方法注冊(cè) Bean
2.2 使用工廠方法和實(shí)例化工廠注冊(cè) Bean
首先還是使用 XML 自建庫(kù),在 Main 方法中對(duì)庫(kù)進(jìn)行操作(這里對(duì)庫(kù)的操作主要是打印 Bean)
import org.springframework.context.support.FileSystemXmlApplicationContext; public class Main { public static void main(String[] args) { FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("spring-config.xml"); String[] names = context.getBeanDefinitionNames(); for (String name : names) { Object bean = context.getBean(name); String canonicalName = bean.getClass().getCanonicalName(); System.out.println(name + " " + canonicalName); } int count = context.getBeanDefinitionCount(); System.out.println("一共有 " + count + "個(gè)"); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 通過(guò)工廠注冊(cè),bean 的實(shí)例化由工廠方法完成--> <bean id="工廠注冊(cè)" class="com.hsq.ioc3.SomeClass" factory-method="createPerson"/> <!-- 通過(guò)已經(jīng)注冊(cè)的 bean 的實(shí)例方法注冊(cè),bean 的實(shí)例化由我們自己完成--> <bean id="工具bean" class="com.hsq.ioc3.SomeClass"/> <bean id="通過(guò)實(shí)例化工廠注冊(cè)" factory-bean="工具bean" factory-method="instantCreatePerson"/> </beans>
public class SomeClass { // 靜態(tài)方法(可以直接通過(guò)類名調(diào)用) // 作用:返回一個(gè)對(duì)象 // 這類方法被稱為工廠方法 public static Person createPerson() { System.out.println("createPerson 被調(diào)用"); return new Person(); } public Person instantCreatePerson() { System.out.println("instantCreatePerson 被調(diào)用"); return new Person(); } }
public class Person { public Person() { System.out.println("Person 被調(diào)用"); } }
通過(guò)打印可以清楚的看到兩種方法都成功注冊(cè) Person 對(duì)象
3. XML 配合注解進(jìn)行 Bean 注冊(cè)
自建 XML 庫(kù)中的配置文件有所改變
用到的注解 @Component,此注解后邊會(huì)講到
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 掃描這個(gè)包下的所有類,如果沒在這個(gè)包下,即使加了注解接不會(huì)被注入--> <context:component-scan base-package="com.hsq.ioc3"/> </beans>
import org.springframework.stereotype.Component; @Component public class World { public World() { System.out.println("World 被調(diào)用"); } }
通過(guò)打印可以清楚看到,World 對(duì)象被成功注冊(cè)
4. 使用注解注冊(cè) Bean
使用注解注冊(cè)簡(jiǎn)而言之就是使用某個(gè)注解修飾類或方法,對(duì)其進(jìn)行注冊(cè)
使用注解注冊(cè) Bean 是注冊(cè)進(jìn) Spring 提供的庫(kù),就不需要自建庫(kù)了
4.1 注解方式注冊(cè)的必要條件
- 要被注解修飾類
- 被注冊(cè)的 Bean 要在 XXXApplication 所在包下,否則注冊(cè)不會(huì)成功
4.2 用到的注解
這幾個(gè)注解在 IOC 場(chǎng)景下,沒有區(qū)別,都是將類注冊(cè)進(jìn) Spring 庫(kù),但在其他場(chǎng)景一般這樣用
@Component:沒有特殊作用時(shí),都可以用
@Controller:SpringMVC中把此注解特殊化了,要求控制器類必須用此注解修飾
@Service:修飾中間數(shù)據(jù)整合的類
@Repository:修飾數(shù)據(jù)獲取類
@Configuration:修飾配置類
4.3 @Component注解注入
import org.springframework.stereotype.Component; @Component public class World { public World() { System.out.println("World() 被調(diào)用"); } }
@SpringBootApplication public class IocAApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(IocAApplication.class, args); String[] names = context.getBeanDefinitionNames(); System.out.println("bean 陳列如下:"); for (String name : names) { Object bean = context.getBean(name); String canonicalName = bean.getClass().getCanonicalName(); System.out.println(name + " " + canonicalName); } int count = context.getBeanDefinitionCount(); System.out.println("一共 " + count + "個(gè)"); } }
通過(guò)打印清楚看到,對(duì)象被注冊(cè)
4.4 使用 @Bean 注解注冊(cè)
使用 @Bean 修飾方法,@Configuration 修飾類
此方法注冊(cè)就相當(dāng)于 XML 中的工廠方法注冊(cè)
@Configuration public class AppConfig { // <bean id="hsq" factory-bean="appConfig" factory-method="hsq" /> // 以工廠方法注冊(cè) @Bean public String hsq() { return "hsq"; } @Bean // 這里的 World 由 Spring 注入 // 因?yàn)?createHello 被 Spring 調(diào)用 public Hello createHello(@Autowired World world) { System.out.println("createHello(), world = " + world); return new Hello(world); } }
5. 通過(guò)注解注入 Bean
需要用到 World 類時(shí)
- 先讓 Hello 類被注冊(cè)到 Spring 容器,并且實(shí)例化過(guò)程交給 Spring。———— @Component 修飾 Hello 類
- 要求 World 類被注冊(cè)到 Spring 中(類注冊(cè)或者方法注冊(cè)都可以)
- 使用構(gòu)造方法、set 方法、屬性直接注入三種方法注入bean——使用 @Autowired 修飾
import org.springframework.stereotype.Component; @Component public class World { public World() { System.out.println("World() 被調(diào)用"); } }
構(gòu)造方法注入
@Component public class Hello { @Autowired // 這個(gè)注解其實(shí)可以不寫,但是建議寫上,主要是讓看代碼的人知道我們的 World 對(duì)象是被注入的 // 如果有多個(gè)構(gòu)造方法,告訴 Spring,實(shí)例化對(duì)象是,應(yīng)該調(diào)用哪個(gè) public Hello(World world) { System.out.println("Hello(), world = " + world); } }
set 方法注入
@Component public class Hello2 { @Autowired // 這里的此注解必須寫上 public void setWorld(World world) { System.out.println("setWorld(), World = " + world); } }
屬性直接注入
@Component public class Hello3 { @Autowired public World world; // world 屬性的值會(huì)被 Spring 容器對(duì)象注入 public void printWorld() { System.out.println("printWorld(), world = " + this.world); } }
6. 注入時(shí)的一個(gè)坑點(diǎn)
當(dāng)使用以下方法注入時(shí),會(huì)注入進(jìn) NULL 值,而非對(duì)象,原因已在下面代碼的注釋中寫出
// 發(fā)生在 set 注入 / 屬性直接注入上 @Component public class 注入時(shí)的一個(gè)坑點(diǎn) { @Autowired public World world; public 注入時(shí)的一個(gè)坑點(diǎn)() { // 構(gòu)造方法先執(zhí)行,然后再進(jìn)行注入(屬性注入 / set 注入) // 所以,構(gòu)造方法執(zhí)行的時(shí)候,注入還沒有發(fā)生,所以還是 null // 所以一般建議使用構(gòu)造方法注入 System.out.println("注入時(shí)的一個(gè)坑點(diǎn)(), world = " + this.world); } }
7. 獲取 庫(kù)中的對(duì)象
ConfigurableApplicationContext context = SpringApplication.run(IocAApplication.class, args); Object world1 = context.getBean("world"); // 根據(jù) id 獲取 bean World world2 = context.getBean(World.class); // 根據(jù)類型獲取 bean World world = context.getBean("world", World.class); // 根據(jù) id + 類型獲取 bean
到此這篇關(guān)于Spring Bean注冊(cè)與注入實(shí)現(xiàn)方法詳解的文章就介紹到這了,更多相關(guān)Spring Bean注冊(cè)與注入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java動(dòng)態(tài)代理實(shí)現(xiàn)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
動(dòng)態(tài)代理作為代理模式的一種擴(kuò)展形式,廣泛應(yīng)用于框架(尤其是基于AOP的框架)的設(shè)計(jì)與開發(fā),本文將通過(guò)實(shí)例來(lái)講解Java動(dòng)態(tài)代理的實(shí)現(xiàn)過(guò)程2017-08-08SpringBoot實(shí)現(xiàn)發(fā)送短信的示例代碼
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)發(fā)送短信的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04springboot配置內(nèi)存數(shù)據(jù)庫(kù)H2教程詳解
這篇文章主要介紹了springboot配置內(nèi)存數(shù)據(jù)庫(kù)H2的詳細(xì)教程,需要的朋友可以參考下2017-07-07spring-cloud-gateway啟動(dòng)踩坑及解決
這篇文章主要介紹了spring-cloud-gateway啟動(dòng)踩坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2021-08-08Java語(yǔ)言描述存儲(chǔ)結(jié)構(gòu)與鄰接矩陣代碼示例
這篇文章主要介紹了Java語(yǔ)言描述存儲(chǔ)結(jié)構(gòu)與鄰接矩陣代碼示例,涉及Java存儲(chǔ)結(jié)構(gòu),鄰接矩陣,鄰接表的介紹與比較,然后分享了鄰接矩陣的Java實(shí)現(xiàn)等相關(guān)內(nèi)容,具有一定借鑒價(jià)值,需要的朋友可以參考。2017-11-11解決idea中java出現(xiàn)無(wú)效的源發(fā)行版問題
這篇文章主要給大家介紹了關(guān)于解決idea中java出現(xiàn)無(wú)效的源發(fā)行版問題的相關(guān)資料,無(wú)效的源發(fā)行版是指IntelliJ IDEA無(wú)法正確識(shí)別和處理的源代碼版本,這可能是由于錯(cuò)誤的配置、缺少依賴項(xiàng)、不兼容的插件或其他問題導(dǎo)致的,需要的朋友可以參考下2024-01-01Mybatis-Plus中updateById方法不能更新空值問題解決
本文主要介紹了Mybatis-Plus中updateById方法不能更新空值問題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08