Jersey採用HK2作為Dependency Injection framework,可以透過簡單的設定將實作的程式inject到interface.有使用過這樣功能的使用者會發現到,僅限於Restful layer可以做inject,非Restful layer就不能inject.
例如:
Interface:1
2
3
4
public interface Bar {
void bar();
}
Implement Bar1
2
3
4
5
6
7
public class BarImpl implements Bar {
public void bar() {
log.info("Bar");
}
}
Background task1
2
3
4
5
6
7
8
9
10
11
12public class CrazyThread {
Bar bar;
public void run() {
new Thread(() -> {
while (true) {
bar.bar();
}
}).start();
}
}
Inject BarImpl into Bar1
2
3
4
5
6
7
8
9
10
11
12public class MyApplication extends ResourceConfig {
public MyApplication() {
this.register(new AbstractBinder() {
protected void configure() {
bind(BarImpl.class).to(Bar.class).in(Singleton.class);
});
new CrazyThread().run();
}
}
會發現沒有辦法順利將BarImpl注射到Bar,因為CraztThread並不在container中,所以沒有辦法順利注射.
首先,我們可以透過HK2 Metadata Generator幫我們達成,它會產生注射的設定檔到META-INF/hk2-locator/default
下.要確認Jersey使用的hk2版本,再匯入相關的jar檔.例如:jersey 2.22.1
使用的hk2版本為2.4.0-b31
,hk2-utils,hk2-api,hk2-metadata-generator一定要為2.4.0-b31
.1
2
3
4compile 'javax.inject:javax.inject:1'
compile group: 'org.glassfish.hk2', name: 'hk2-utils', version: '2.4.0-b31'
compile group: 'org.glassfish.hk2', name: 'hk2-api', version: '2.4.0-b31'
compile group: 'org.glassfish.hk2', name: 'hk2-metadata-generator', version: '2.4.0-b31'
修改CrazyThread,加入@Service
1
2
3
4
5
6
7
8
9
10
11
12
13
public class CrazyThread {
Bar bar;
public void run() {
new Thread(() -> {
while (true) {
bar.bar();
}
}).start();
}
}
最後修改MyApplication,透過ServiceLocator
取得CrazyThread
1
2
3
4
5
6
7public class MyApplication extends ResourceConfig {
public MyApplication() {
ServiceLocator serviceLocator = ServiceLocatorUtilities.createAndPopulateServiceLocator();
final CrazyThread crazyThread = serviceLocator.getService(CrazyThread.class);
crazyThread.run();
}
}
大功告成!!!
後記
在Jersey中使用HK2這個問題困惱我很久,很多沒有在resource層使用到的程式,就沒有辦法透過hk2注入.Using HK2 with Jersey (with auto-scanning!)這篇文章有提到怎麼解決這個問題,可能是早期版本的hk2必須手動去hack,嘗試他的做法不能順利執行.後來參考了jersey + grizzly + hk2: Dependency injection, but not into resource和khasunuma/hk2-sample才解決這個問題…