Большинство 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.
@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-файлов приложения
@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 Вконтакте.
Использованные материалы:
- docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
- Ссылка на проект на github: github.com/saladinkzn/social-vkontakte-spring-boot-starter
ссылка на оригинал статьи http://habrahabr.ru/post/275337/