Spring Dynamic Modules (Spring Dm) значительно упрощает разработку приложений на базе OSGi . При этом развертывание сервисов становится намного проще. Вы можете добавить сервисы, как и любые другие бобы Spring.
Итак, начнем с Spring dm.
Прежде всего, вам необходимо скачать Spring Dm Distribution . В этой статье я использовал дистрибутивы с зависимостями и буду использовать только эти библиотеки:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
com.springsource.net.sf.cglib-2.1.3.jar com.springsource.org.aopalliance-1.0.0.jar log4j.osgi-1.2.15-SNAPSHOT.jar com.springsource.slf4j.api-1.5.0.jar com.springsource.slf4j.log4j-1.5.0.jar com.springsource.slf4j.org.apache.commons.logging-1.5.0.jar org.springframework.aop-2.5.6.SEC01.jar org.springframework.beans-2.5.6.SEC01.jar org.springframework.context-2.5.6.SEC01.jar org.springframework.core-2.5.6.SEC01.jar spring-osgi-core-1.2.1.jar spring-osgi-extender-1.2.1.jar spring-osgi-io-1.2.1.jar |
Конечно, вы можете заменить библиотеки Spring 2.5.6 библиотеками Spring 3.0. Но для этой статьи Spring 2.5.6 будет достаточно.
Итак, начнем с пакета услуг. Если мы помним, этот пакет экспортировал один сервис:
1
2
3
4
5
|
package com.bw.osgi.provider.able; public interface HelloWorldService { void hello(); } |
01
02
03
04
05
06
07
08
09
10
|
package com.bw.osgi.provider.impl; import com.bw.osgi.provider.able.HelloWorldService; public class HelloWorldServiceImpl implements HelloWorldService { @Override public void hello(){ System.out.println( "Hello World !" ); } } |
Здесь нет никаких изменений. Теперь мы можем увидеть активатор:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package com.bw.osgi.provider; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import com.bw.osgi.provider.able.HelloWorldService; import com.bw.osgi.provider.impl.HelloWorldServiceImpl; public class ProviderActivator implements BundleActivator { private ServiceRegistration registration; @Override public void start(BundleContext bundleContext) throws Exception { registration = bundleContext.registerService( HelloWorldService. class .getName(), new HelloWorldServiceImpl(), null ); } @Override public void stop(BundleContext bundleContext) throws Exception { registration.unregister(); } } |
Итак, здесь мы сделаем все просто. Давайте удалим этот класс, это больше не полезно с Spring Dm.
Мы позволим Spring Dm экспортировать пакет для нас. Мы создадим контекст Spring для этого пакета. Нам просто нужно создать файл provider-context.xml в папке META-INF / spring . Это простой контекст в XML-файле, но мы используем новое пространство имен для регистрации службы: « http://www.springframework.org/schema/osgi «. Итак, начнем :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation=" < bean id = "helloWorldService" class = "com.bw.osgi.provider.impl.HelloWorldServiceImpl" /> < osgi:service ref = "helloWorldService" interface = "com.bw.osgi.provider.able.HelloWorldService" /> </ beans > |
Единственное, что специфично для OSGi — это объявление osgi: service. Эта строка указывает, что мы регистрируем helloWorldService в качестве службы OSGi, используя интерфейс HelloWorldService в качестве имени службы.
Если вы поместите файл контекста в папку META-INF / spring , он будет автоматически обнаружен Spring Extender и будет создан контекст приложения.
Теперь мы можем перейти к потребительской пачке. На первом этапе мы создали этого потребителя:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package com.bw.osgi.consumer; import javax.swing.Timer; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import com.bw.osgi.provider.able.HelloWorldService; public class HelloWorldConsumer implements ActionListener { private final HelloWorldService service; private final Timer timer; public HelloWorldConsumer(HelloWorldService service) { super (); this .service = service; timer = new Timer( 1000 , this ); } public void startTimer(){ timer.start(); } public void stopTimer() { timer.stop(); } @Override public void actionPerformed(ActionEvent e) { service.hello(); } } |
В настоящее время здесь нет никаких изменений. Вместо внедрения с помощью конструктора мы могли бы использовать аннотацию @Resource, но это не работает в Spring 2.5.6 и Spring Dm (но хорошо работает в Spring 3.0).
А теперь активатор:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package com.bw.osgi.consumer; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import com.bw.osgi.provider.able.HelloWorldService; public class HelloWorldActivator implements BundleActivator { private HelloWorldConsumer consumer; @Override public void start(BundleContext bundleContext) throws Exception { ServiceReference reference = bundleContext.getServiceReference(HelloWorldService. class .getName()); consumer = new HelloWorldConsumer((HelloWorldService) bundleContext.getService(reference)); consumer.startTimer(); } @Override public void stop(BundleContext bundleContext) throws Exception { consumer.stopTimer(); } } |
Инъекция больше не нужна. Мы можем сохранить запуск таймера здесь, но еще раз, мы можем использовать функции инфраструктуры для запуска и остановки таймера. Итак, давайте удалим активатор и создадим контекст приложения, чтобы создать потребителя, запустить его автоматически и поместить в папку META-INF / spring :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
<? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation=" < bean id = "consumer" class = "com.bw.osgi.consumer.HelloWorldConsumer" init-method = "startTimer" destroy-method = "stopTimer" lazy-init = "false" > < constructor-arg ref = "eventService" /> </ bean > < osgi:reference id = "eventService" interface = "com.bw.osgi.provider.able.HelloWorldService" /> </ beans > |
Мы использовали атрибуты init-method и destroy-method для запуска и остановки времени в фреймворке, и мы используем конструктор-arg, чтобы внедрить ссылку на сервис. Ссылка на сервис получается с использованием поля osgi: reference и с использованием интерфейса в качестве ключа к сервису.
Это все, что нам нужно сделать с этим комплектом. Намного проще, чем в первой версии, не так ли? И помимо упрощения, вы можете видеть, что источники не зависят ни от OSGi, ни от Spring Framework, это простая Java и это большое преимущество.
POM Maven такие же, как на первом этапе, за исключением того, что мы можем сократить зависимость от OSGI.
Провайдер:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<? xml version = "1.0" encoding = "UTF-8" ?> < modelVersion >4.0.0</ modelVersion > < groupId >OSGiDmHelloWorldProvider</ groupId > < artifactId >OSGiDmHelloWorldProvider</ artifactId > < version >1.0</ version > < packaging >bundle</ packaging > < build > < plugins > < plugin > < groupId >org.apache.maven.plugins</ groupId > < artifactId >maven-compiler-plugin</ artifactId > < version >2.0.2</ version > < configuration > < source >1.6</ source > < target >1.6</ target > </ configuration > </ plugin > < plugin > < groupId >org.apache.felix</ groupId > < artifactId >maven-bundle-plugin</ artifactId > < extensions >true</ extensions > < configuration > < instructions > < Bundle-SymbolicName >OSGiDmHelloWorldProvider</ Bundle-SymbolicName > < Export-Package >com.bw.osgi.provider.able</ Export-Package > < Bundle-Vendor >Baptiste Wicht</ Bundle-Vendor > </ instructions > </ configuration > </ plugin > </ plugins > </ build > </ project > |
Потребитель:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
<? xml version = "1.0" encoding = "UTF-8" ?> < modelVersion >4.0.0</ modelVersion > < groupId >OSGiDmHelloWorldConsumer</ groupId > < artifactId >OSGiDmHelloWorldConsumer</ artifactId > < version >1.0</ version > < packaging >bundle</ packaging > < dependencies > < dependency > < groupId >OSGiDmHelloWorldProvider</ groupId > < artifactId >OSGiDmHelloWorldProvider</ artifactId > < version >1.0</ version > </ dependency > </ dependencies > < build > < plugins > < plugin > < groupId >org.apache.maven.plugins</ groupId > < artifactId >maven-compiler-plugin</ artifactId > < version >2.0.2</ version > < configuration > < source >1.6</ source > < target >1.6</ target > </ configuration > </ plugin > < plugin > < groupId >org.apache.felix</ groupId > < artifactId >maven-bundle-plugin</ artifactId > < extensions >true</ extensions > < configuration > < instructions > < Bundle-SymbolicName >OSGiDmHelloWorldConsumer</ Bundle-SymbolicName > < Bundle-Vendor >Baptiste Wicht</ Bundle-Vendor > </ instructions > </ configuration > </ plugin > </ plugins > </ build > </ project > |
И мы можем собрать два пакета, используя maven install. Итак, давайте проверим наши вещи в Феликсе:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
wichtounet@Linux-Desktop:~ /Desktop/osgi/felix $ java -jar bin /felix .jar _______________ Welcome to Apache Felix Gogo g! install file :.. /com .springsource.slf4j.org.apache.commons.logging-1.5.0.jar Bundle ID: 5 g! install file :.. /com .springsource.slf4j.log4j-1.5.0.jar Bundle ID: 6 g! install file :.. /com .springsource.slf4j.api-1.5.0.jar Bundle ID: 7 g! install file :.. /log4j .osgi-1.2.15-SNAPSHOT.jar Bundle ID: 8 g! install file :.. /com .springsource.net.sf.cglib-2.1.3.jar Bundle ID: 9 g! install file :.. /com .springsource.org.aopalliance-1.0.0.jar Bundle ID: 10 g! install file :.. /org .springframework.core-2.5.6.SEC01.jar Bundle ID: 11 g! install file :.. /org .springframework.context-2.5.6.SEC01.jar Bundle ID: 12 g! install file :.. /org .springframework.beans-2.5.6.SEC01.jar Bundle ID: 13 g! install file :.. /org .springframework.aop-2.5.6.SEC01.jar Bundle ID: 14 g! install file :.. /spring-osgi-extender-1 .2.1.jar Bundle ID: 15 g! install file :.. /spring-osgi-core-1 .2.1.jar Bundle ID: 16 g! install file :.. /spring-osgi-io-1 .2.1.jar Bundle ID: 17 g! start 5 7 8 9 10 11 12 13 14 15 16 17 log4j:WARN No appenders could be found for logger (org.springframework.osgi.extender.internal.activator.ContextLoaderListener). log4j:WARN Please initialize the log4j system properly. g! install file :.. /OSGiDmHelloWorldProvider-1 .0.jar Bundle ID: 18 g! install file :.. /OSGiDmHelloWorldConsumer-1 .0.jar Bundle ID: 19 g! start 18 g! start 19 g! Hello World ! Hello World ! Hello World ! Hello World ! Hello World ! Hello World ! Hello World ! Hello World ! stop 19 g! |
Как видите, работает отлично!
В заключение, Spring Dm действительно облегчает разработку с OSGi. С Spring Dm вы также можете запускать связки. Он также позволяет создавать веб-пакеты и легко пользоваться услугами компендиума OSGi.
Вот источники двух проектов:
Вот непосредственно две сборочные банки:
И вот полная папка, включая Felix и Spring Dm: osgi-hello-world.tar.gz
Ссылка: OSGI и Spring Dynamic Modules — Simple Hello World от нашего партнера JCG Баптиста Вихта в