溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何在Java中運(yùn)用依賴注入

發(fā)布時(shí)間:2021-05-17 15:21:29 來(lái)源:億速云 閱讀:365 作者:Leah 欄目:開(kāi)發(fā)技術(shù)

今天就跟大家聊聊有關(guān)如何在Java中運(yùn)用依賴注入,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

一、C++的詬病

C++最遭人詬病的地方就是定義一個(gè)類需要寫(xiě)兩個(gè)文件,一個(gè).h文件和一個(gè).cpp文件。例如定義一個(gè)CMainFrame類,mainframe.h內(nèi)容如下:

class CMainFrame : public CFrameWndEx
{
protected:
	CMainFrame();
public:
	virtual ~CMainFrame();
};

mainframe.cpp內(nèi)容如下:

CMainFrame::CMainFrame()
{
}
 
CMainFrame::~CMainFrame()
{
}

當(dāng)需要給這個(gè)類添加一個(gè)方法時(shí),需要同時(shí)修改.h文件和.cpp文件。例如新增一個(gè)DefWindowProc函數(shù)。需要在.h文件中增加該函數(shù)的聲明。

class CMainFrame : public CFrameWndEx
{
protected:
	CMainFrame();
public:
	virtual ~CMainFrame();
 
protected:
	virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);
};

mainframe.cpp中增加DefWindowProc的定義:

LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	if(message==WM_NCPAINT ) 
	{
		if(bShow){
			ShowWindow(SW_SHOW);
		}
		else {
			ShowWindow(SW_HIDE);
		}
	}
 
	return CFrameWndEx::DefWindowProc(message, wParam, lParam);
}

可以看出C++的類定義代碼中,一次變化需要修改兩個(gè)文件,其維護(hù)的繁瑣令人詬病。

二、Java的改進(jìn)

然而Java的出現(xiàn)徹底解決了這個(gè)問(wèn)題,一個(gè)類就對(duì)應(yīng)一個(gè).java文件(包括后來(lái)其他面向?qū)ο笳Z(yǔ)言也秉承了這個(gè)思路,比如C#)。

比如一個(gè)LogService類用于對(duì)日志進(jìn)行維護(hù),起初只包含日志的增刪功能,LogService.java代碼如下。

public class LogService{
	public ServiceResult<Boolean> addLog (SysLogInfo logInfo) {
		......
	}
 
	public ServiceResult<Boolean> delLog (String id) {
		......
	}
}

當(dāng)需要增加一個(gè)updateLog方法時(shí),僅需對(duì)LogService.java進(jìn)行修改。

public class LogService{
	public ServiceResult<Boolean> addLog (SysLogInfo logInfo) {
		......
	}
 
	public ServiceResult<Boolean> delLog(String id) {
		......
	}
 
	public ServiceResult<Boolean> updateLog (SysLogInfo logInfo) {
		......
	}
 
}

一切變得方便了很多。

三、誤用導(dǎo)致的退步

但是最近在看一些基于Spring(SpringBoot、SpringMVC)框架寫(xiě)的代碼時(shí),發(fā)現(xiàn)很多類的代碼又回到了C++的形式。例如在使用一個(gè)LogService時(shí),開(kāi)發(fā)人員首先定義了一個(gè)interface,在LogService.java中:

public interface LogService {
	ServiceResult<Boolean> addLog(SysLogInfo logInfo);
	ServiceResult<Boolean> delLog(String id);
}

然后定義了一個(gè)該接口的實(shí)現(xiàn)類,在LogServiceImpl.java中:

public class LogServiceImpl implements LogService{
	
	@Override
	public ServiceResult<Boolean> addLog(SysLogInfo logInfo) {
		......		
	}
 
	@Override
	public ServiceResult<Boolean> delLog(String id) {
		......
	}
}

在需要實(shí)例化這個(gè)類的地方用了一個(gè)@Autowired注解注入。

public class LogController {
	@Autowired
	private LogService logservice;
}

在問(wèn)及開(kāi)發(fā)人員為什么要象這樣做時(shí),其給了一個(gè)自信的回答:這是面向接口編程!

注意:這個(gè)設(shè)計(jì)中LogService.java類似于C++中的.h文件,LogServiceImpl.java類似于C++中的.cpp文件,這兩個(gè)文件共同定義了一個(gè)LogService類。當(dāng)需要給這個(gè)類添加一個(gè)updateLog方法時(shí),LogService.java和LogServiceImpl.java都需要被修改,又走回了C++的老路。這顯然是對(duì)面向接口編程的曲解。如果這樣都能算面向接口編程的話,那么C++就成了一門(mén)天然的面向接口編程的語(yǔ)言,還何必去學(xué)那些復(fù)雜的設(shè)計(jì)模式。

不過(guò)這樣寫(xiě)代碼有什么問(wèn)題嗎?其實(shí)也沒(méi)有太大問(wèn)題,只是代碼繁瑣一點(diǎn)而已(C++就是這樣的)。只不過(guò)既然你選擇了Java語(yǔ)言,卻又寫(xiě)成了C++的樣子,就好像在開(kāi)一輛自動(dòng)擋的汽車,卻一直撥到手動(dòng)模式駕駛一樣。

四、正確理解面向接口編程

那么什么才是面向接口編程呢,其要點(diǎn)在于:接口是基于變化的抽象。在有可能變化的地方才需要接口。假設(shè)上面的例子中,寫(xiě)日志的動(dòng)作同時(shí)存在3種不同的實(shí)現(xiàn):

1.寫(xiě)到日志文件。

2.寫(xiě)到數(shù)據(jù)庫(kù)。

3.寫(xiě)到本地的一個(gè)日志服務(wù)的UDP端口。

那么可以基于這個(gè)接口寫(xiě)3個(gè)不同的實(shí)現(xiàn)類:

public class LogServiceFile implements LogService{
}
public class LogServiceDB implements LogService{
}
public class LogServiceUdp implements LogService{
}

當(dāng)然此時(shí)如果還是使用下面的代碼會(huì)報(bào)錯(cuò),因?yàn)锳utowired只能裝配對(duì)應(yīng)接口的唯一一個(gè)派生類的Bean,而此時(shí)存在3個(gè)派生類。

public class LogController {
	@Autowired
	private LogService logservice;
}

需要改進(jìn)成類似下面這個(gè)樣子,根據(jù)實(shí)際情況使用對(duì)應(yīng)的派生類對(duì)象:

public class LogController {
	private LogService logservice;
	void writeLog(SysLogInfo logInfo){
		logservice = GetLogServiceInst();
		logservice.addLog(logInfo);
	}
}

Java的優(yōu)點(diǎn)是什么

1. 簡(jiǎn)單,只需理解基本的概念,就可以編寫(xiě)適合于各種情況的應(yīng)用程序;2. 面向?qū)ο螅?. 分布性,Java是面向網(wǎng)絡(luò)的語(yǔ)言;4. 魯棒性,java提供自動(dòng)垃圾收集來(lái)進(jìn)行內(nèi)存管理,防止程序員在管理內(nèi)存時(shí)容易產(chǎn)生的錯(cuò)誤。;5. 安全性,用于網(wǎng)絡(luò)、分布環(huán)境下的Java必須防止病毒的入侵。6. 體系結(jié)構(gòu)中立,只要安裝了Java運(yùn)行時(shí)系統(tǒng),就可在任意處理器上運(yùn)行。7. 可移植性,Java可以方便地移植到網(wǎng)絡(luò)上的不同機(jī)器。8.解釋執(zhí)行,Java解釋器直接對(duì)Java字節(jié)碼進(jìn)行解釋執(zhí)行。

看完上述內(nèi)容,你們對(duì)如何在Java中運(yùn)用依賴注入有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI