SPI機(jī)制:為某個(gè)接口尋找服務(wù)實(shí)現(xiàn)的機(jī)制
我們提供的服務(wù)有:做網(wǎng)站、網(wǎng)站制作、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、凱里ssl等。為成百上千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的凱里網(wǎng)站制作公司
java SPI就是提供這樣的一個(gè)機(jī)制 ,需要在META-INF目錄中設(shè)置接口的實(shí)現(xiàn),以實(shí)現(xiàn)服務(wù)接口與實(shí)現(xiàn)的解耦。第三方服務(wù)廠商或者插件服務(wù),可以依據(jù)SPI機(jī)制,實(shí)現(xiàn)功能擴(kuò)展。
在Spring中也有一種類(lèi)似與Java SPI的加載機(jī)制。它在META-INF/spring.factories文件中配置接口的實(shí)現(xiàn)類(lèi),我們成為Spring factories機(jī)制,基于此我們可以自定義stater或SDK供他人使用,項(xiàng)目只在pom.xml中引入SDK,無(wú)須配置即可實(shí)現(xiàn)功能集成。
最近的需求為例,需要實(shí)現(xiàn)授權(quán)功能SDK,以供其他產(chǎn)品使用
項(xiàng)目目錄結(jié)構(gòu)如下
第一步:在包名root目錄下創(chuàng)建自動(dòng)配置類(lèi)?EsbrSdkAutoConfig
內(nèi)容如下:添加
@Configuration
@ComponentScan(basePackageClasses = EsbrSdkAutoConfig.class)
標(biāo)識(shí)此類(lèi)為配置類(lèi),并配置掃描路徑為當(dāng)前類(lèi)
第二步;? ? 在resources/META-IN目錄下,創(chuàng)建spring.factories文件
內(nèi)容如下:
將org.springframework.boot.autoconfigure.EnableAutoConfiguration的自動(dòng)配置為值設(shè)置為第一步的EsbrSdkAutoConfig的全限定類(lèi)名(包名+類(lèi)名)
第三步:編寫(xiě)SDK的Service
通過(guò)以上三步,即可基于Spring factories機(jī)制完成自定義Starter,在其他項(xiàng)目pom.xml中引入該starter即可
是不是很簡(jiǎn)單,下面講解下原理
spring-core包里定義了SpringFactoriesLoader類(lèi),這個(gè)類(lèi)實(shí)現(xiàn)了檢索META-INF/spring.factories文件中的配置,
并通過(guò) loadFactoryNames方法() 獲取其接口類(lèi)的名稱
在這個(gè)方法中會(huì)遍歷整個(gè)ClassLoader中所有jar包下的spring.factories文件。也就是說(shuō)我們可以在自己的jar中配置spring.factories文件,不會(huì)影響到其它地方的配置,也不會(huì)被別人的配置覆蓋。
將org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.org.bjca.esbr.sdk.EsbrSdkAutoConfig
基于springboot自動(dòng)配置,會(huì)掃描并初始化EsbrSdkAutoConfig類(lèi),并將EsbrSdkAutoConfig作為basepackage,掃描改類(lèi)及其該類(lèi)子包下的類(lèi),加載到spring容器。
首先下載播放mp3的包,比如mp3spi1.9.4.jar。在工程中添加這個(gè)包。
播放器演示代碼如下
package?com.test.audio;
import?java.io.File;
import?java.awt.BorderLayout;
import?java.awt.FileDialog;
import?java.awt.Frame;
import?java.awt.GridLayout;
import?java.awt.Label;
import?java.awt.List;
import?java.awt.Menu;
import?java.awt.MenuBar;
import?java.awt.MenuItem;
import?java.awt.MenuShortcut;
import?java.awt.Panel;
import?java.awt.event.ActionEvent;
import?java.awt.event.ActionListener;
import?java.awt.event.KeyEvent;
import?java.awt.event.MouseAdapter;
import?java.awt.event.MouseEvent;
import?java.awt.event.WindowAdapter;
import?java.awt.event.WindowEvent;
import?javax.sound.sampled.AudioFormat;
import?javax.sound.sampled.AudioInputStream;
import?javax.sound.sampled.AudioSystem;
import?javax.sound.sampled.DataLine;
import?javax.sound.sampled.SourceDataLine;
public?class?MusicPlayer?extends?Frame?{
/**
?*?
?*/
private?static?final?long?serialVersionUID?=?-2605658046194599045L;
boolean?isStop?=?true;//?控制播放線程
boolean?hasStop?=?true;//?播放線程狀態(tài)
String?filepath;//?播放文件目錄
String?filename;//?播放文件名稱
AudioInputStream?audioInputStream;//?文件流
AudioFormat?audioFormat;//?文件格式
SourceDataLine?sourceDataLine;//?輸出設(shè)備
List?list;//?文件列表
Label?labelfilepath;//播放目錄顯示標(biāo)簽
Label?labelfilename;//播放文件顯示標(biāo)簽
public?MusicPlayer()?{
//?設(shè)置窗體屬性
setLayout(new?BorderLayout());
setTitle("MP3?Music?Player");
setSize(350,?370);
//?建立菜單欄
MenuBar?menubar?=?new?MenuBar();
Menu?menufile?=?new?Menu("File");
MenuItem?menuopen?=?new?MenuItem("Open",?new?MenuShortcut(KeyEvent.VK_O));
menufile.add(menuopen);
menufile.addActionListener(new?ActionListener()?{
public?void?actionPerformed(ActionEvent?e)?{
open();
}
});
menubar.add(menufile);
setMenuBar(menubar);
//?文件列表
list?=?new?List(10);
list.addMouseListener(new?MouseAdapter()?{
public?void?mouseClicked(MouseEvent?e)?{
//?雙擊時(shí)處理
if?(e.getClickCount()?==?2)?{
//?播放選中的文件
filename?=?list.getSelectedItem();
play();
}
}
});
add(list,?"Center");
//?信息顯示
Panel?panel?=?new?Panel(new?GridLayout(2,?1));
labelfilepath?=?new?Label("Dir:");
labelfilename?=?new?Label("File:");
panel.add(labelfilepath);
panel.add(labelfilename);
add(panel,?"North");
//?注冊(cè)窗體關(guān)閉事件
addWindowListener(new?WindowAdapter()?{
public?void?windowClosing(WindowEvent?e)?{
System.exit(0);
}
});
setVisible(true);
}
//?打開(kāi)
private?void?open()?{
FileDialog?dialog?=?new?FileDialog(this,?"Open",?0);
dialog.setVisible(true);
filepath?=?dialog.getDirectory();
if?(filepath?!=?null)?{
labelfilepath.setText("Dir:"?+?filepath);
//?顯示文件列表
list.removeAll();
File?filedir?=?new?File(filepath);
File[]?filelist?=?filedir.listFiles();
for?(File?file?:?filelist)?{
String?filename?=?file.getName().toLowerCase();
if?(filename.endsWith(".mp3")?||?filename.endsWith(".wav"))?{
list.add(filename);
}
}
}
}
//?播放
private?void?play()?{
try?{
isStop?=?true;//?停止播放線程
//?等待播放線程停止
System.out.print("Start:"?+?filename);
while?(!hasStop)?{
System.out.print(".");
try?{
Thread.sleep(10);
}?catch?(Exception?e)?{
}
}
System.out.println("");
File?file?=?new?File(filepath?+?filename);
labelfilename.setText("Playing:"?+?filename);
//?取得文件輸入流
audioInputStream?=?AudioSystem.getAudioInputStream(file);
audioFormat?=?audioInputStream.getFormat();
//?轉(zhuǎn)換mp3文件編碼
if?(audioFormat.getEncoding()?!=?AudioFormat.Encoding.PCM_SIGNED)?{
audioFormat?=?new?AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
audioFormat.getSampleRate(),?16,?audioFormat
.getChannels(),?audioFormat.getChannels()?*?2,
audioFormat.getSampleRate(),?false);
audioInputStream?=?AudioSystem.getAudioInputStream(audioFormat,
audioInputStream);
}
//?打開(kāi)輸出設(shè)備
DataLine.Info?dataLineInfo?=?new?DataLine.Info(
SourceDataLine.class,?audioFormat,
AudioSystem.NOT_SPECIFIED);
sourceDataLine?=?(SourceDataLine)?AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(audioFormat);
sourceDataLine.start();
//?創(chuàng)建獨(dú)立線程進(jìn)行播放
isStop?=?false;
Thread?playThread?=?new?Thread(new?PlayThread());
playThread.start();
}?catch?(Exception?e)?{
e.printStackTrace();
}
}
class?PlayThread?extends?Thread?{
byte?tempBuffer[]?=?new?byte[320];
public?void?run()?{
try?{
int?cnt;
hasStop?=?false;
//?讀取數(shù)據(jù)到緩存數(shù)據(jù)
while?((cnt?=?audioInputStream.read(tempBuffer,?0,
tempBuffer.length))?!=?-1)?{
if?(isStop)
break;
if?(cnt??0)?{
//?寫(xiě)入緩存數(shù)據(jù)
sourceDataLine.write(tempBuffer,?0,?cnt);
}
}
//?Block等待臨時(shí)數(shù)據(jù)被輸出為空
sourceDataLine.drain();
sourceDataLine.close();
hasStop?=?true;
}?catch?(Exception?e)?{
e.printStackTrace();
System.exit(0);
}
}
}
public?static?void?main(String?args[])?{
new?MusicPlayer();
}
}
str[0]="";
如果你要判斷的話用這個(gè)式子保險(xiǎn)
if(str[0] != null str[0].length() != 0){
;}
在eclipse里面試一下啊,有debug選項(xiàng)在spit后面設(shè)置斷點(diǎn),然后進(jìn)入debug,到變量空間里面看看即可!