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.jarcom.springsource.org.aopalliance-1.0.0.jarlog4j.osgi-1.2.15-SNAPSHOT.jarcom.springsource.slf4j.api-1.5.0.jarcom.springsource.slf4j.log4j-1.5.0.jarcom.springsource.slf4j.org.apache.commons.logging-1.5.0.jarorg.springframework.aop-2.5.6.SEC01.jarorg.springframework.beans-2.5.6.SEC01.jarorg.springframework.context-2.5.6.SEC01.jarorg.springframework.core-2.5.6.SEC01.jarspring-osgi-core-1.2.1.jarspring-osgi-extender-1.2.1.jarspring-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 Gogog! install file:../com.springsource.slf4j.org.apache.commons.logging-1.5.0.jarBundle ID: 5g! install file:../com.springsource.slf4j.log4j-1.5.0.jarBundle ID: 6g! install file:../com.springsource.slf4j.api-1.5.0.jarBundle ID: 7g! install file:../log4j.osgi-1.2.15-SNAPSHOT.jarBundle ID: 8g! install file:../com.springsource.net.sf.cglib-2.1.3.jarBundle ID: 9g! install file:../com.springsource.org.aopalliance-1.0.0.jarBundle ID: 10g! install file:../org.springframework.core-2.5.6.SEC01.jarBundle ID: 11g! install file:../org.springframework.context-2.5.6.SEC01.jarBundle ID: 12g! install file:../org.springframework.beans-2.5.6.SEC01.jarBundle ID: 13g! install file:../org.springframework.aop-2.5.6.SEC01.jarBundle ID: 14g! install file:../spring-osgi-extender-1.2.1.jarBundle ID: 15g! install file:../spring-osgi-core-1.2.1.jarBundle ID: 16g! install file:../spring-osgi-io-1.2.1.jarBundle ID: 17g! start 5 7 8 9 10 11 12 13 14 15 16 17log4j: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.jarBundle ID: 18g! install file:../OSGiDmHelloWorldConsumer-1.0.jarBundle ID: 19g! start 18g! start 19g! Hello World !Hello World !Hello World !Hello World !Hello World !Hello World !Hello World !Hello World !stop 19g! |
Как видите, работает отлично!
В заключение, Spring Dm действительно облегчает разработку с OSGi. С Spring Dm вы также можете запускать связки. Он также позволяет создавать веб-пакеты и легко пользоваться услугами компендиума OSGi.
Вот источники двух проектов:
Вот непосредственно две сборочные банки:
И вот полная папка, включая Felix и Spring Dm: osgi-hello-world.tar.gz
Ссылка: OSGI и Spring Dynamic Modules — Simple Hello World от нашего партнера JCG Баптиста Вихта в