java 有參數的構造函數如何注入_Spring5參考指南:依賴注入

依賴注入

依賴注入就是在Spring創建Bean的時候,去實例化該Bean構造函數所需的參數,或者通過Setter方法去設置該Bean的屬性。

Spring的依賴注入有兩種基于構造函數的依賴注入和基于setter的依賴注入。

基于構造函數的依賴注入

構造函數的注入是通過構造函數的參數來實現的。如下所示:

public class ExampleBean {// Number of years to calculate the Ultimate Answerprivate int years;// The Answer to Life, the Universe, and Everythingprivate String ultimateAnswer;public ExampleBean(int years, String ultimateAnswer) {this.years = years;this.ultimateAnswer = ultimateAnswer;}}?

該Bean有一個兩個參數的構造函數,那么怎么注入這些參數呢?

有三種方法。

方法1:按構造函數的類型匹配:

這里通過指定參數的類型,即可以指定哪個參數是years,哪個參數是ultimateAnswer。

方法2:構造函數索引:

Spring中可以通過構造函數的索引來指定特定的參數。要注意Spring的索引是從0開始的。

方法3:構造函數名字匹配:

如果通過構造函數的名字來匹配,需要注意必須在編譯的時候開啟調試標志,要不然Spring不能在構造函數中找到參數名。

如果不想啟用調試標志,則必須使用@ConstructorProperties JDK注解顯式命名構造函數參數。

public class ExampleBeanWithConstructorProperties {// Number of years to calculate the Ultimate Answerprivate int years;// The Answer to Life, the Universe, and Everythingprivate String ultimateAnswer;@ConstructorProperties ({"years", "ultimateAnswer"})public ExampleBeanWithConstructorProperties (int years, String ultimateAnswer) {this.years = years;this.ultimateAnswer = ultimateAnswer;}}

基于Setter的注入

Setter注入主要用來無參構造器或者獲得對象實例之后才設置對象的屬性。下面是Setter的例子:

public class SimpleMovieLister {// the SimpleMovieLister has a dependency on the MovieFinderprivate MovieFinder movieFinder;// a setter method so that the Spring container can inject a MovieFinderpublic void setMovieFinder (MovieFinder movieFinder) {this.movieFinder = movieFinder;}// business logic that actually uses the injected MovieFinder is omitted...}

對于的XML文件如下:

除了XML配置,也可以使用注解:@Component、@Controller。或者使用@Configuration注解中的@Bean方法。

如何選擇?

既然有這樣兩種注入方式,我們怎么選擇呢?

通常來說,對于必須的屬性,我們通過構造函數來注入。對于可選屬性,我們通過Setter注入。當然你也可以在Setter方法中使用@Required注解。

當然如果第三方類不公開任何setter方法,那么構造函數注入可能是DI的唯一可用形式。

循環依賴

循環依賴主要出現在構造函數注入的情況。

類A通過構造函數注入需要類B的實例,類B通過構造函數注入需要類A的實例。如果為要相互注入的類A和類B配置bean,那么SpringIOC容器在運行時檢測到這個循環引用,會拋出BeanCurrentlyInCreationException。

解決方式就是使用Setter注入。

依賴注入的配置詳解

基本類型,字符串或者其他

如果< property/>元素的value屬性是基本類型,Spring會將其轉換為類需要的類型,配置如下:

這是一個常見的Setter注入。為了簡潔,也可以使用p-namespace,如下:

<?xml version="1.0" encoding="UTF-8"?>

Spring容器使用JavaBeans屬性編輯器機制將< value/>元素中的文本轉換為java.util.properties實例。這是一個很好的快捷方式,如下所示:

jdbc.driver.className= com.mysql.jdbc.Driverjdbc.url=jdbc: mysql://localhost:3306/mydb

注意上面例子中的value里面的值。

ref

通過< ref/>標記的bean屬性允許在同一容器或父容器中創建對任何bean的引用,而不管它是否在同一XML文件中。bean屬性的值可以與目標bean的id屬性相同,也可以與目標bean的name屬性中的一個值相同。以下示例顯示如何使用ref元素:

內部bean

在< property/> 或者 < constructor-arg/>元素內部的< bean/>元素可以定義一個內部bean,下面是個例子:

內部bean定義不需要ID或名稱。如果指定,容器也不會使用這個值作為標識符。容器在創建時也忽略作用域標志,因為內部bean總是匿名的,并且總是用外部bean創建的。不可能單獨訪問內部bean,也不可能將它們注入到除封閉bean之外的協作bean中。

集合

< list/>, < set/>, < map/>,和 < props/> 分別被用來設置Java Collection類型List, Set, Map,和 Properties 類型的屬性和參數。 下面是個例子:

 administrator@example.org support@example.org development@example.org"a list element followed by a reference"just some string

強類型集合

通過在Java 5中引入泛型類型,可以使用強類型集合。也就是說,可以聲明集合類型,使其只能包含(例如)字符串元素。如果使用Spring將強類型集合注入bean,則可以利用Spring的類型轉換支持,以便在將強類型集合實例的元素添加到集合之前將其轉換為適當的類型。下面的Java類和bean定義的例子:

public class SomeClass {private Map accounts;public void setAccounts (Map accounts) {this.accounts = accounts;}}

Null和Empty字符串值

Null和空字符串是不一樣的,如下:

上面的例子相當于:

exampleBean.setEmail("");

下面是怎么設置null:

上面的例子相當于:

exampleBean.setEmail(null);

c-namespace

上面講到了p-namespace專門是設置bean的屬性用的,同樣的c-namespace是用來設置構造函數參數的,如下所示:

depends-on

通常一個bean依賴另一個bean,我們會在XML中使用< ref/>來引用,但是這種依賴關系并不直接。我們可以使用depends-on屬性來顯式強制一個或多個bean在使用此元素的bean初始化之前進行初始化,如下所示:

lazy-init

正常來說ApplicationContext中配置成單例模式的bean都會隨Spring啟動而初始化,如果有特殊的需要,想延長初始化該bean,則可以使用 lazy-init 。一個lazy-initialized bean告訴IOC容器在第一次請求bean實例時創建它,而不是在啟動時。

但是,當一個惰性初始化bean是一個非惰性初始化的singleton bean的依賴項時,ApplicationContext會在啟動時創建惰性初始化bean,因為它必須滿足singleton的依賴項。

您還可以通過在< beans/>元素上使用默認的lazy init屬性在容器級別控制lazy初始化,下面的示例顯示:

自動裝載

如果你想讓Spring自動幫你注入bean的依賴bean時候,可以使用Spring的autowiring功能。autowiring 有4種模式:

76f5ec65e933f6c982974dc731bcd08a.png

自動注入的限制和缺陷

雖然自動注入用起來很爽,但是它也有如下的缺陷:

property和constructor-arg的顯示設置會覆蓋自動注入,并且自動注入不能注入簡單類型。

自動注入不如顯示配置精確。

自動注入可能和容器中的很多bean相匹配。可能會出現問題。

從自動裝載中排除Bean

使用autowire-candidate屬性設置為false,可以防止bean被自動注入。該屬性只會影響按類型注入的方式。如果按name注入,則不受影響。

下面是自動注入的例子:

SimpleMovieLister如下:

package com.flydean.beans;import lombok.Data;@Datapublic class SimpleMovieLister {// the SimpleMovieLister has a dependency on the MovieFinderprivate MovieFinder movieFinder;// a setter method so that the Spring container can inject a MovieFinderpublic void setMovieFinder (MovieFinder movieFinder) {this.movieFinder = movieFinder;}// business logic that actually uses the injected MovieFinder is omitted...}

在上面的例子中,movieFinder屬性將會被自動注入。

方法注入

在bean的生命周期不同的時候,如果一個bean要依賴于另外一個bean則可能出現問題。 比如一個單例模式的beanA 依賴于多例模式的beanB。 因為beanA是單例模式的,所以在創建beanA的時候就已經將其依賴的beanB創建了,不可能在每次beanA需要beanB的時候都創建一個新的beanB的實例。

解決方法有很多種,我們一一進行講解。

方法1:實現ApplicationContextAware

如果實現了ApplicationContextAware,則可以通過getBean方法在每次需要beanB的時候,請求他的新的實例,如下:

public class CommandManager implements ApplicationContextAware {private ApplicationContext applicationContext;public Object process (Map commandState) {// grab a new instance of the appropriate CommandCommand command = createCommand();// set the state on the (hopefully brand new) Command instancecommand.setState(commandState);return command.execute();}protected Command createCommand() {// notice the Spring API dependency!return this.applicationContext.getBean ("command", Command.class);}public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}}

這種方法并不可取的,因為業務代碼和Spring框架產生了耦合。方法注入是Spring IoC 容器的一個高級特性,它可以很好的處理這種情況。

查找方法注入

查找方法注入是指容器重寫container-managed bean上的方法,并返回容器中另一個命名bean。查找通常涉及一個原型bean,如前一節中描述的場景中所示。Spring框架通過使用cglib庫中的字節碼動態生成覆蓋該方法的子類來實現該方法注入。

因為使用了cglib,所以bean不能是final類,方法也不能是final類型。

查找方法不適用于工廠方法,尤其不適用于配置類中的@Bean方法,因為在這種情況下,容器不負責創建實例,因此無法動態創建運行時生成的子類。

下面是一個查找方法的例子:

public abstract class CommandManagerB {public Object process (Map commandState) {// grab a new instance of the appropriate Command interfaceAsyncCommand command = createCommand();return null;}// okay... but where is the implementation of this method?public abstract AsyncCommand createCommand();}

這里我們定義了一個抽象類,要查找的方法就是createCommand。返回的對象類,如下:

public class AsyncCommand {}

下面是XML配置文件:

CommandMangerB每次調用createCommand,都會返回一個新的AsyncCommand實例。

在基于注解的情況下,也可以這樣使用:

public abstract class CommandManagerC {public Object process (Object commandState) {Command command = createCommand();return command.execute();}@Lookup("myCommand")protected abstract Command createCommand();}

其中@Lookup(“myCommand”) 中的名字也可以省略,則按照默認的類型來解析。

任意方法替換

我們甚至可以使用replaced-method替換bean的方法實現。我們有個MyValueCalculator類,有一個我們想重寫的方法computeValue。

public class MyValueCalculator {public String computeValue(String input) {// some real code...return "abc";}// some other methods...}

一個實現了org.springframework.beans.factory.support.MethodReplacer接口的類提供了新的方法,如下所示:

public class ReplacementComputeValue implements MethodReplacer {public Object reimplement (Object o, Method m, Object[] args) throws Throwable {// get the input value, work with it, and return a computed resultString input = (String) args[0];return "def";}}

bean的定義如下:

String

本章的例子可以參考bean-di中的bean-di部分。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/396243.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/396243.shtml
英文地址,請注明出處:http://en.pswp.cn/news/396243.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深度學習去燥學習編碼_我們問了15,000個人,他們是誰,以及他們如何學習編碼

深度學習去燥學習編碼More than 15,000 people responded to the 2016 New Coder Survey, granting researchers an unprecedented glimpse into how adults are learning to code.超過15,000人對2016年新編碼器調查做出了回應&#xff0c;使研究人員對成年人如何學習編碼有了前…

CentOS 7 vi編輯命令

用vi打開一個yum文件 vi /usr/bin/yum 按 i 鍵后 進入insert模式&#xff0c;進入insert模式后才能進行修改 修改完成后 按esc鍵進入command模式&#xff0c; 然后:wq 保存文件并退出vi&#xff08;注意先冒號&#xff09; 保存命令 按ESC鍵 跳到命令模式&#xff0c;然后&…

C#學習筆記四: C#3.0自動屬性匿名屬性及擴展方法

前言 這一章算是看這本書最大的收獲了, Lambda表達式讓人用著屢試不爽, C#3.0可謂顛覆了我們的代碼編寫風格. 因為Lambda所需篇幅挺大, 所以先總結C#3.0智能編譯器給我們帶來的諸多好處, 下一遍會單獨介紹Lambda表達式. 這篇主要包括的內容有: 自動屬性,隱式類型,對象集合初始化…

array keys php,php array_keys與array_search的簡單使用

函數說明array_keys():返回數組中所有的鍵名。array_search():在數組中搜索給定的值&#xff0c;如果成功則返回相應的鍵名。//根據一個key返回關聯數組中的另一個key,并且不使用foreach// function array_key_relative(array $array, string $current_key, int $offset)functi…

RESTful服務的第三部分:HATEOAS和Richardson成熟度模型

by Sanchit Gera通過Sanchit Gera RESTful服務的第三部分&#xff1a;HATEOAS和Richardson成熟度模型 (RESTful Services Part III : HATEOAS and The Richardson Maturity Model) In Part I of this series, you learned the very basics of HTTP. We went over common HTTP …

mongdb集群3.4 shard 模式

從圖中可以看到有四個組件&#xff1a;mongos、config server、shard、replica set。mongos&#xff1a;數據庫集群請求的入口&#xff0c;所有的請求都通過mongos進行協調&#xff0c;不需要在應用程序添加一個路由選擇器&#xff0c;mongos自己就是一個請求分發中心&#xff…

我想變得富有的10個理由

1.我想和娘家人住得近一些&#xff0c;可以經常見面、聊天、逛街、吃飯。我們需要彼此的時候&#xff0c;可以馬上趕到。 2.我想在家人病痛的時候&#xff0c;能得到最好的救治。 3.我想住在干凈寬敞的大房子里&#xff0c;不要和長輩住^_^ 4.我希望不用我動手&#xff0c;家里…

alpha值計算 qcolor_量化交易與機器學習(四):如何研究alpha因子

算法交易策略由指示何時購買或出售資產以產生相對于基準&#xff08;例如指數&#xff09;的較高回報的信號驅動。 資產回報率中未通過暴露于該基準而無法解釋的部分稱為alpha&#xff0c;因此旨在產生這種不相關收益的信號也稱為alpha因子。本章主要介紹alpha因子一、從數據到…

項目啟動及需求分析(靳嘉豪、胡新宇、李晨曦、楊航、李瑤)團隊作業

&#xff08;1&#xff09; 這次團隊我們給我們團隊起的名字是&#xff1a;橋上吊刀刀倒吊著 隊員分別為&#xff1a;靳嘉豪、胡新宇、李晨曦、李瑤、楊航。 隊訓為&#xff1a;黑化肥揮發發灰會揮發。 胡新宇&#xff1a;http://www.cnblogs.com/hxy94264/ 靳嘉豪&#xff1a;…

java兩種傳參,有關java參數的兩種傳遞機制

值傳遞&#xff1a;方法調用時&#xff0c;實際參數把它的值傳遞給對應的形式參數&#xff0c;方法執行中形式參數值的改變不影響實際參 數的值。引用傳遞&#xff1a;也稱為傳地址。方法調用時&#xff0c;實際參數的引用(地址&#xff0c;而不是參數的值)被傳遞給方法中相對應…

tcp選項部分編碼_學習編碼中最難的部分也是最有趣的部分

tcp選項部分編碼by Corey Slaven通過Corey Slaven 學習編碼中最難的部分也是最有趣的部分 (The hardest part of learning to code is also the funnest part) “The more you know, the more you know you don’t know.”“知道的越多&#xff0c;知道的越多。” ― Aristotl…

SCU 4439 Vertex Cover(二分圖最小覆蓋點)題解

題意&#xff1a;每一條邊至少有一個端點要涂顏色&#xff0c;問最少涂幾個點 思路&#xff1a;最小頂點覆蓋&#xff1a;用最少的點&#xff0c;讓每條邊都至少和其中一個點關聯&#xff0c;顯然是道裸最小頂點覆蓋題&#xff1b; 參考&#xff1a;二分圖 代碼&#xff1a; #i…

20155229 實驗一《Java開發環境的熟悉》實驗報告

20155229 實驗一《Java開發環境的熟悉》實驗報告 實驗內容 1.使用JDK編譯、運行簡單的Java程序&#xff1b; 2.使用Idea 編輯、編譯、運行、調試Java程序。 實驗步驟 &#xff08;一&#xff09;命令行下Java程序開發 輸入 mkdir 20155229命令建立實驗目錄&#xff0c;用ls查看…

js時間搓化為今天明天_js轉時間戳,時間戳轉js

js轉時間戳轉此時此刻的時間1、var timestamp1 (new Date()).valueOf();valueOf() 方法返回指定對象的原始值2、var timestamp2 new Date().getTime();Date.prototype.getTime()方法的返回值一個數值&#xff0c;表示從1970年1月1 日0時0分0秒(UTC&#xff0c;即協調世界時)距…

PHP代碼20個實用技巧(轉)

這些技巧特別是封裝的&#xff0c;相對路徑的還是挺好的&#xff0c;本身來自微信公眾號&#xff0c;但是我擔心以后刪除&#xff0c;所以在我的博客上備份一下&#xff08;微信公眾號為:菜鳥教程&#xff09; 在這篇文章中我們將看看一些關于PHP開發有用的提示和技巧&#xff…

需求簡報_代碼簡報:NASA將所有研究成果發布為開放數據

需求簡報Here are three stories we published this week that are worth your time:這是我們本周發布的三個值得您關注的故事&#xff1a; With open data, you finally get what you’ve paid for all these years: 4 minute read 有了開放的數據&#xff0c;您終于可以得到…

matlab 16位灰度值轉8位,在matlab中如何將灰度值為24位的轉化為8?

我使用的是Visual c6。0技術內幕里提供的類CDib來操作位圖&#xff0c;最好提供可以兩個獨立的函數來分辨別實現著倆個功能。他們可以作為CDib類的成員函數來使用。類似下面的這個就可以&#xff0c;我用了下面的這個&#xff0c;但是下面這個不好用&#xff0c;處理后的圖象有…

quartz基本使用

創建一個任務調度 Scheduler scheduler StdSchedulerFactory.getDefaultScheduler();//Schedulers can be immediately used to schedule jobs, but they will not start executing any until the .start()scheduler.start();//And then schedule those jobs with triggers th…

em模型補缺失值_基于EM算法數據單變量缺失處理方法研究

龍源期刊網http://www.qikan.com.cn基于EM算法數據單變量缺失處理方法研究作者&#xff1a;黃鉉來源&#xff1a;《科技傳播》2015年第20期摘要數據分析方法大都針對完整數據&#xff0c;而實際上由于一些原因&#xff0c;觀測數據常存在缺失。本文采用EM算法對正態分布下的隨機…

流媒體協議介紹(rtp/rtcp/rtsp/rtmp/mms/hls)

RTP 參考文檔 RFC3550/RFC3551 Real-time Transport Protocol)是用于Internet上針對多媒體數據流的一種傳輸層協議。RTP協議詳細說明了在互聯網上傳遞音頻和視頻的標準數據包格式。RTP協議常用于流媒體系統&#xff08;配合RTCP協議&#xff09;&#xff0c;視…