Пишем свой spring-boot-starter

Большинство java-разработчиков уже познакомились с проектом Spring Boot, позволяющим быстро написать приложение, использующее различные компоненты Spring Framework (Spring MVC, Spring Data и многие другие).

Всё удобство Spring Boot основано на использовании так называемых Starter, которые позволяют получить набор сконфигурированных бинов, готовых к использованию и доступных для конфигурации через properties-файлы. Но что делать, если для нужной технологии еще не написано стартера?

В этой статье мне бы хотелось рассказать о том, как создаются стартеры на примере стартера для Spring-social-vkontakte. Spring Social это один из модулей Spring Framework, используемый для интеграции с социальными сетями. В проект Spring Boot включены стартеры для таких социальных сетей как Facebook (spring-boot-starter-social-facebook), Twitter (spring-boot-starter-social-twitter) и LinkedIn (spring-boot-starter-social-twitter), основанные на использовании соответствующих Social-модулей. Большинство разработчиков из СНГ интересует в первую очередь социальная сеть Вконтакте, для которой существует сторонний модуль spring-social-vkontakte. Соответственно, стартера для этого модуля еще нет. Написанием этого стартера мы и займемся в этой статье.

Краеугольным камнем инфраструктуры Spring Boot являются AutoConfiguration-классы, которые Spring Boot находит при запуске приложения и использует для автоматического создания и конфигурирования бинов.

Создадим такой класс для нашего стартера:

@Configuration @ConditionalOnClass({SocialConfigurerAdapter.class, VKontakteConnectionFactory.class}) @ConditionalOnProperty(prefix= "ru.shadam.social-vkontakte", name = { "client-id", "client-secret"}) @AutoConfigureBefore(SocialWebAutoConfiguration.class) @AutoConfigureAfter(WebMvcAutoConfiguration.class) public class VKontakteAutoConfiguration { } 

Мы используем аннотации, чтобы указать SpringBoot, что наш класс является конфигурацией (@Configuration), аннотации, чтобы задать условия, при которых наш AutoConfiguration будет использоваться для создания бинов, а также аннотации, чтобы указать каково место нашей автоконфигурации в процедуре инициализации приложения.

Таким образом:

@ConditionalOnClass({SocialConfigurerAdapter.class, VKontakteConnectionFactory.class}) 

означает, что бины будут создаваться при наличии в classpath SocialConfigurerAdapter(входит в модуль Spring-Social) и VKontakteConnectionFactory (входит в модуль Spring-Social-Vkontakte). Таким образом, без нужных для нашего стартера зависимостей бины создаваться не будут.

@ConditionalOnProperty(prefix= "ru.shadam.social-vkontakte", name = { "client-id", "client-secret"}) 

означает, что бины будут создаваться только при наличии property ru.shadam.social-vkontakte.client-id и ru.shadam.social-vkontakte.client-secret.

@AutoConfigureBefore(SocialWebAutoConfiguration.class) @AutoConfigureAfter(WebMvcAutoConfiguration.class) 

означает, что наш бин будет инициализироваться после WebMvc и до SocialWeb. Это нужно, чтобы к моменту инициализации SocialWeb наши бины уже были зарегистрированы.

Теперь перейдем к тому, какие бины мы сконфигурируем в нашем AutoConfiguration.

VKontakteAutoConfiguration.java

@Configuration @ConditionalOnClass({SocialConfigurerAdapter.class, VKontakteConnectionFactory.class}) @ConditionalOnProperty(prefix= "ru.shadam.social-vkontakte", name = { "client-id", "client-secret"}) @AutoConfigureBefore(SocialWebAutoConfiguration.class) @AutoConfigureAfter(WebMvcAutoConfiguration.class) public class VKontakteAutoConfiguration {      @Configuration     @EnableSocial     @EnableConfigurationProperties(VKontakteProperties.class)     @ConditionalOnWebApplication     protected static class VKontakteConfigurationAdapter extends SocialConfigurerAdapter {          @Autowired         private VKontakteProperties properties;          @Bean         @ConditionalOnMissingBean         @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)         public VKontakte vkontakte(ConnectionRepository repository) {             Connection<VKontakte> connection = repository.findPrimaryConnection(VKontakte.class);             if (connection != null) {                 return connection.getApi();             }             return new VKontakteTemplate(this.properties.getClientId(), this.properties.getClientSecret());         }          private ConnectionFactory<?> createConnectionFactory() {             return new VKontakteConnectionFactory(this.properties.getClientId(), this.properties.getClientSecret());         }          @Override         public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer, Environment environment) {             connectionFactoryConfigurer.addConnectionFactory(createConnectionFactory());         }     } } 

Расширяем SocialConfigurationAdapter, который нужен для того чтобы зарегистрировать нашу ConnectionFactory. Для этого в SocialConfigurerAdapter есть callback-метод:

addConnectionFactories(ConnectionFactoryConfigurer, Environment)

Его мы и переопределим, добавляя нашу ConnectionFactory.

Также зарегистрируем request-scoped бин Vkontakte, которые представляет собой интерфейс для доступа к API Вконтакте. При этом, если пользователь авторизуется через приложение, то операции взаимодействия с API будет выполнено с использованием auth_token.

Рассмотрим также класс VkontakteProperties, который используется для получения конфигурации из properties-файлов приложения

VkontakteProperties.java

@ConfigurationProperties(prefix = "ru.shadam.social-vkontakte") public class VKontakteProperties  {     private String clientId;     private String clientSecret;      public String getClientId() {         return clientId;     }      public void setClientId(String clientId) {         this.clientId = clientId;     }      public String getClientSecret() {         return clientSecret;     }      public void setClientSecret(String clientSecret) {         this.clientSecret = clientSecret;     } } 

За получение значений из properties файлов отвечает аннотация:

@ConfigurationProperties(prefix = "ru.shadam.social-vkontakte") 

Она сообщает SpringBoot, что нужно попытаться все проперти, начинающиеся с префикса ru.shadam.social-vkontakte поместить в соответствующие поля класса.

Последним нашим шагом будет создание файла, позволяющего SpringBoot найти наш AutoConfiguration класс. Для этого существует специальный файл spring.factories, который нужно поместить в META-INF папку получающегося jar-файла.

В этом файле нам надо указать наш AutoConfiguration-класс.

org.springframework.boot.autoconfigure.EnableAutoConfiguration=ru.shadam.spring.boot.vkontakte.VKontakteAutoConfiguration 

Теперь, подключив получившийся jar к нашему Spring Boot проекту и задав в конфигурации ru.shadam.social-vkontakte.client-id и ru.shadam.social-vkontakte.client-secret, мы получим в нашем приложении сконфигруированные пути /connect/vkontakte и бин Vkontakte, который мы можем использовать для доступа к API Вконтакте.

Использованные материалы:

  1. docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
  2. Ссылка на проект на github: github.com/saladinkzn/social-vkontakte-spring-boot-starter

ссылка на оригинал статьи http://habrahabr.ru/post/275337/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *