赞
踩
一. 简介:
当我们使用一个spring外部组件时,通常需要依赖多个不同的jar包,spring-boot-starter能够整合所需要的依赖组件,通过根据模块内的环境进行自动配置,使用者只需要引入starter坐标,不需要过多的依赖及配置就可以使用
- 1.它整合了这个模块需要的依赖库;
- 2.提供对模块的配置项给使用者;
- 3.提供自动配置类对模块内的Bean进行自动装配;
例如:使用微信公众号开源脚手架只需要引入下面的wx-java-mp-starter依赖即可,不需要手动对其其他组件依赖
二. 编写starter开发步骤
1.新建maven项目,并添加以下依赖
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-autoconfigure</artifactId>
- <version>${spring.boot.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-configuration-processor</artifactId>
- <version>${spring.boot.version}</version>
- <optional>true</optional>
- </dependency>
- <dependency>
其中 spring-boot-configuration-processor
的作用是编译时生成 spring-configuration-metadata.json
,此文件主要给IDE使用。如当配置此jar相关配置属性在 application.yml
,你可以用ctlr+鼠标左键点击属性名,IDE会跳转到你配置此属性的类中。
spring官方starter一般采取spring-boot-starter-{name}的命名方式,如spring-boot-starter-web,非官方建议artifactId命名遵循{name}-spring-boot-starter, wx-java-mp-starter的命名如下:
wx-java-mp-starter
2. 新建配置类(微信app相关信息配置类)
- package com.binarywang.spring.starter.wxjava.mp;
-
- import lombok.Data;
- import org.springframework.boot.context.properties.ConfigurationProperties;
-
- import java.io.Serializable;
-
- import static com.binarywang.spring.starter.wxjava.mp.WxMpProperties.PREFIX;
- import static com.binarywang.spring.starter.wxjava.mp.WxMpProperties.StorageType.memory;
-
-
- /**
- * 微信接入相关配置属性
- */
- @Data
- @ConfigurationProperties(PREFIX)
- public class WxMpProperties {
- public static final String PREFIX = "wx.mp";
-
- /**
- * 设置微信公众号的appid
- */
- private String appId;
-
- /**
- * 设置微信公众号的app secret
- */
- private String secret;
-
- /**
- * 设置微信公众号的token
- */
- private String token;
-
- /**
- * 设置微信公众号的EncodingAESKey
- */
- private String aesKey;
-
- /**
- * 存储策略, memory, redis
- */
- private ConfigStorage configStorage = new ConfigStorage();
-
-
- @Data
- public static class ConfigStorage implements Serializable {
-
- private StorageType type = memory;
-
- private RedisProperties redis = new RedisProperties();
-
- }
-
- public enum StorageType {
- memory, redis
- }
- }
- package com.binarywang.spring.starter.wxjava.mp;
-
- import lombok.Data;
- import org.springframework.boot.context.properties.ConfigurationProperties;
-
- import java.io.Serializable;
-
- import static com.binarywang.spring.starter.wxjava.mp.WxMpProperties.PREFIX;
- import static com.binarywang.spring.starter.wxjava.mp.WxMpProperties.StorageType.memory;
-
-
- /**
- * 微信接入相关配置属性
- */
- @Data
- @ConfigurationProperties(PREFIX)
- public class WxMpProperties {
- public static final String PREFIX = "wx.mp";
-
- /**
- * 设置微信公众号的appid
- */
- private String appId;
-
- /**
- * 设置微信公众号的app secret
- */
- private String secret;
-
- /**
- * 设置微信公众号的token
- */
- private String token;
-
- /**
- * 设置微信公众号的EncodingAESKey
- */
- private String aesKey;
-
- /**
- * 存储策略, memory, redis
- */
- private ConfigStorage configStorage = new ConfigStorage();
-
-
- @Data
- public static class ConfigStorage implements Serializable {
-
- private StorageType type = memory;
-
- private RedisProperties redis = new RedisProperties();
-
- }
-
- public enum StorageType {
- memory, redis
- }
- }
3. 新建总配置类,用于springboot 加载配置
第一步: SpringBoot 在启动时会去依赖的starter包中寻找 resources/META-INF/spring.factories
文件,然后根据文件中配置的Jar包去扫描项目所依赖的Jar包,这类似于 Java 的 SPI 机制,此类将配置在spring.factories中
第二步: 根据 spring.factories
配置加载AutoConfigure
类。
最后,根据 @Conditional
注解的条件,进行自动配置并将Bean注入Spring Context 上下文当中。
我们也可以使用@ImportAutoConfiguration({MyServiceAutoConfiguration.class})
指定自动配置哪些类。
- package com.binarywang.spring.starter.wxjava.mp;
-
- import org.springframework.boot.context.properties.EnableConfigurationProperties;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.Import;
-
- @Configuration
- @EnableConfigurationProperties(WxMpProperties.class)
- @Import({WxMpStorageAutoConfiguration.class, WxMpServiceAutoConfiguration.class})
- public class WxMpAutoConfiguration {
- }
4.新建导入配置类即第三步中的Import所导入的类,因application包扫描扫描并未配置第三方jar引用,所以通过import的方式将实例注到spring容器
- package com.binarywang.spring.starter.wxjava.mp;
-
- import me.chanjar.weixin.mp.api.WxMpConfigStorage;
- import me.chanjar.weixin.mp.api.WxMpService;
- import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- /**
- * 微信公众号相关服务自动注册
- */
- @Configuration
- public class WxMpServiceAutoConfiguration {
- @Autowired
- private ApplicationContext ctx;
-
- @Bean
- @ConditionalOnMissingBean//通过此注解,可以自已实现一个WxMpConfigStorage来替换此存储策略
- public WxMpService wxMpService(WxMpConfigStorage configStorage) {
- WxMpService wxMpService = new WxMpServiceImpl();
- wxMpService.setWxMpConfigStorage(configStorage);
- registerWxMpSubService(wxMpService);
- return wxMpService;
- }
-
- @ConditionalOnBean(WxMpService.class)
- public Object registerWxMpSubService(WxMpService wxMpService) {
- //进行bean单例注册,注册后可注入使用
- ConfigurableListableBeanFactory factory = (ConfigurableListableBeanFactory) ctx.getAutowireCapableBeanFactory();
- factory.registerSingleton("wxMpKefuService", wxMpService.getKefuService());
- factory.registerSingleton("wxMpMaterialService", wxMpService.getMaterialService());
- factory.registerSingleton("wxMpMenuService", wxMpService.getMenuService());
- factory.registerSingleton("wxMpUserService", wxMpService.getUserService());
- factory.registerSingleton("wxMpUserTagService", wxMpService.getUserTagService());
- factory.registerSingleton("wxMpQrcodeService", wxMpService.getQrcodeService());
- factory.registerSingleton("wxMpCardService", wxMpService.getCardService());
- factory.registerSingleton("wxMpDataCubeService", wxMpService.getDataCubeService());
- factory.registerSingleton("wxMpUserBlacklistService", wxMpService.getBlackListService());
- factory.registerSingleton("wxMpStoreService", wxMpService.getStoreService());
- factory.registerSingleton("wxMpTemplateMsgService", wxMpService.getTemplateMsgService());
- factory.registerSingleton("wxMpSubscribeMsgService", wxMpService.getSubscribeMsgService());
- factory.registerSingleton("wxMpDeviceService", wxMpService.getDeviceService());
- factory.registerSingleton("wxMpShakeService", wxMpService.getShakeService());
- factory.registerSingleton("wxMpMemberCardService", wxMpService.getMemberCardService());
- factory.registerSingleton("wxMpMassMessageService", wxMpService.getMassMessageService());
- return Boolean.TRUE;
- }
-
- }
- package com.binarywang.spring.starter.wxjava.mp;
-
- import me.chanjar.weixin.mp.api.WxMpConfigStorage;
- import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
- import me.chanjar.weixin.mp.api.WxMpInRedisConfigStorage;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import redis.clients.jedis.JedisPool;
- import redis.clients.jedis.JedisPoolConfig;
-
- /**
- * 微信公众号存储策略自动配置
- */
- @Configuration
- public class WxMpStorageAutoConfiguration {
-
- @Autowired
- private WxMpProperties properties;
-
- @Autowired(required = false)
- private JedisPool jedisPool;
-
- @Bean
- @ConditionalOnMissingBean(WxMpConfigStorage.class)
- public WxMpConfigStorage wxMpInMemoryConfigStorage() {
- WxMpProperties.ConfigStorage storage = properties.getConfigStorage();
- WxMpProperties.StorageType type = storage.getType();
-
- if (type == WxMpProperties.StorageType.redis) {
- return getWxMpInRedisConfigStorage();
- }
- return getWxMpInMemoryConfigStorage();
- }
-
- private WxMpInMemoryConfigStorage getWxMpInMemoryConfigStorage() {
- WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
- setWxMpInfo(config);
- return config;
- }
-
- private WxMpInRedisConfigStorage getWxMpInRedisConfigStorage() {
- JedisPool poolToUse = jedisPool;
- if (poolToUse == null) {
- poolToUse = getJedisPool();
- }
- WxMpInRedisConfigStorage config = new WxMpInRedisConfigStorage(poolToUse);
- setWxMpInfo(config);
- return config;
- }
-
- private void setWxMpInfo(WxMpInMemoryConfigStorage config) {
- config.setAppId(properties.getAppId());
- config.setSecret(properties.getSecret());
- config.setToken(properties.getToken());
- config.setAesKey(properties.getAesKey());
- }
-
- private JedisPool getJedisPool() {
- WxMpProperties.ConfigStorage storage = properties.getConfigStorage();
- RedisProperties redis = storage.getRedis();
-
- JedisPoolConfig config = new JedisPoolConfig();
- if (redis.getMaxActive() != null) {
- config.setMaxTotal(redis.getMaxActive());
- }
- if (redis.getMaxIdle() != null) {
- config.setMaxIdle(redis.getMaxIdle());
- }
- if (redis.getMaxWaitMillis() != null) {
- config.setMaxWaitMillis(redis.getMaxWaitMillis());
- }
- if (redis.getMinIdle() != null) {
- config.setMinIdle(redis.getMinIdle());
- }
- config.setTestOnBorrow(true);
- config.setTestWhileIdle(true);
-
- JedisPool pool = new JedisPool(config, redis.getHost(), redis.getPort(),
- redis.getTimeout(), redis.getPassword(), redis.getDatabase());
- return pool;
- }
- }
5. 最后一步,在resources/META-INF/
下创建spring.factories
文件,并添加如下内容:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.binarywang.spring.starter.wxjava.mp.WxMpAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration
后面的类名为装配的配置类,引入多个使用逗号分开;
springboot启动时会通过org.springframework.core.io.support.SpringFactoriesLoader
读取classpath下每个Starter的spring.factories文件,加载自动装配类进行Bean的自动装配
6. 关于配置中的注解解释
6.1 conditions相关注解
Conditions | 描述 |
---|---|
@ConditionalOnBean | 在存在某个bean的时候 |
@ConditionalOnMissingBean | 不存在某个bean的时候 |
@ConditionalOnClass | 当前classpath可以找到某个类型的类时 |
@ConditionalOnMissingClass | 当前classpath不可以找到某个类型的类时 |
@ConditionalOnResource | 当前classpath是否存在某个资源文件 |
@ConditionalOnProperty | 当前jvm是否包含某个系统属性为某个值 |
@ConditionalOnWebApplication | 当前spring context是否是web应用程序 |
6.2 其他注解
@EnableConfigurationProperties 作用是:使ConfigurationProperties注解生效
@ConfigurationProperties 将配置文件中的属性值映射到类中
@Import 通过导入的方式实现把实例加入springIOC容器中
三. 使用方式
- <dependency>
- <groupId>com.github.binarywang</groupId>
- <artifactId>wx-java-mp-starter</artifactId>
- <version>${weixin-java-mp.version}</version>
- </dependency>
- package com.rograndec.crm.service.wxcoupon.impl;
-
- import com.rograndec.crm.service.wxcoupon.WeiXinCouponService;
- import me.chanjar.weixin.mp.api.WxMpCardService;
- import org.springframework.beans.factory.annotation.Autowired;
-
- /**
- * @author ping.zhu
- * @date 2019-06-03 20:08
- * @description
- */
-
- public class WeiXinCouponServiceImpl implements WeiXinCouponService {
-
- @Autowired
- private WxMpCardService wxMpCardService;
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。