《springboot》springboot自定义starter

 1.查看默认配置,通用.

 

2.先查看源码

META-INF/spring.factories

3.start命名规范

spring提供的starter

spring-boot-starter-web

spring-boot-starter-freemarker 

spring-boot-starter-data-redis

第三方的starter

mybatis-spring-boot-starter

4. starter创建步骤

1.   创建项目,  定义bean

2.   创建AutoConfiguration,  @Bean实例化上面的bean

3.  定义注解,@Import(xxxAutoConfiguration.class)   //引入xxxAutoConfiguration配置类

4. demo项目引入 starter项目, maven引入 spring-boot-configuration-processor

5. 打包

--创建项目,  定义bean

public class LogFilterRegistrationBean extends FilterRegistrationBean<LogFilter> {

    public LogFilterRegistrationBean() {
        super();
        this.setFilter(new LogFilter()); //添加LogFilter过滤器
        this.addUrlPatterns("/*"); // 匹配所有路径
        this.setName("LogFilter"); // 定义过滤器名
        this.setOrder(1); // 设置优先级

    }
}
public class LogFilter implements Filter {


    private Logger logger = LoggerFactory.getLogger(LogFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("-----logFilter init...");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //  从request中获取到访问的地址,并在控制台中打印出来
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        logger.info("-----uri {} is working.", request.getRequestURI());
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        logger.info("-----logFilter destroy...");

    }
}

 --创建AutoConfiguration,  @Bean实例化上面的bean

/**
 * 
 * @author kevin
 *
 */
@Configuration
@ConditionalOnClass({LogFilterRegistrationBean.class, LogFilter.class})
public class LogFilterAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(LogFilterRegistrationBean.class)
    public LogFilterRegistrationBean logFilterRegistrationBean() {
        return new LogFilterRegistrationBean();
    }

}

--定义注解,@Import(xxxAutoConfiguration.class)   //引入xxxAutoConfiguration配置类

/**
 * 
 * @author kevin
 *
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(LogFilterAutoConfiguration.class) //引入LogFilterAutoConfiguration配置类
public @interface EnableLogFilter {
}

 --demo项目引入 starter项目, maven引入 spring-boot-configuration-processor

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>com.kevin</groupId>
			<artifactId>springboot-log-starter</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
@SpringBootApplication
@RestController
@EnableLogFilter
public class SpringbootDemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringbootDemoApplication.class, args);
	}
	
    @GetMapping("/test")
    public String test() {
        return "this is a demo boot.";
    }
}

--打包

pom加入配置

	<build>
       <!-- 打jar包  引入spring.factories-->
		<resources>
			<resource>
				<directory>META-INF</directory>
				<targetPath>META-INF/</targetPath>
			</resource>
		</resources>
	</build>

测试

http://localhost:8080/test

5.批量@Import()

/**
 * 
 * @author kevin
 *
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
//@Import(LogFilterAutoConfiguration.class) //引入LogFilterAutoConfiguration配置类
@Import(EnableLogFilterImportSelector.class) //引入通用批量加载
public @interface EnableLogFilter {
}

下面这个类通用


/**
 * 
 * @author kevin
 *
 */
public class EnableLogFilterImportSelector implements DeferredImportSelector, BeanClassLoaderAware, EnvironmentAware {

	private static final Logger logger = LoggerFactory.getLogger(EnableLogFilterImportSelector.class);

	private ClassLoader beanClassLoader;

	private Class<EnableLogFilter> annotationClass = EnableLogFilter.class;

	private Environment environment;

	@Override
	public String[] selectImports(AnnotationMetadata metadata) {
		// 是否生效,默认为true
		if (!isEnabled()) {
			return new String[0];
		}
		// 获取注解中的属性
		AnnotationAttributes attributes = AnnotationAttributes
				.fromMap(metadata.getAnnotationAttributes(this.annotationClass.getName(), true));

		Assert.notNull(attributes, "No " + getSimpleName() + " attributes found. Is " + metadata.getClassName()
				+ " annotated with @" + getSimpleName() + "?");
		
		// 从spring.factories中获取所有通过EnableLogFilter注解引入的自动配置类,并进行去重操作
		List<String> factories = new ArrayList<>(new LinkedHashSet<>(
				SpringFactoriesLoader.loadFactoryNames(this.annotationClass, this.beanClassLoader)));

		if (factories.isEmpty() && !hasDefaultFactory()) {
			throw new IllegalStateException("Annotation @" + getSimpleName()
					+ " found, but there are no implementations. Did you forget to include a starter?");
		}

		if (factories.size() > 1) {

			logger.warn("More than one implementation " + "of @" + getSimpleName()
					+ " (now relying on @Conditionals to pick one): " + factories);
		}

		return factories.toArray(new String[factories.size()]);
	}

	protected boolean hasDefaultFactory() {
		return false;
	}

	protected boolean isEnabled() {
		return true;
	}

	;

	protected String getSimpleName() {
		return this.annotationClass.getSimpleName();
	}

	protected Class<EnableLogFilter> getAnnotationClass() {
		return this.annotationClass;
	}

	protected Environment getEnvironment() {
		return this.environment;
	}

	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;
	}

	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
		this.beanClassLoader = classLoader;
	}

}

List<String> factories = new ArrayList<>(new LinkedHashSet<>(
                SpringFactoriesLoader.loadFactoryNames(this.annotationClass, this.beanClassLoader)));
看这句 

SpringFactoriesLoader .java

	private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
		MultiValueMap<String, String> result = cache.get(classLoader);
		if (result != null) {
			return result;
		}

		try {
			Enumeration<URL> urls = (classLoader != null ?
					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
			result = new LinkedMultiValueMap<>();
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				for (Map.Entry<?, ?> entry : properties.entrySet()) {
					String factoryClassName = ((String) entry.getKey()).trim();
					for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
						result.add(factoryClassName, factoryName.trim());
					}
				}
			}
			cache.put(classLoader, result);
			return result;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
	}
	public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

 定义META-INF/spring.factories

测试如常.

猜你喜欢

转载自blog.csdn.net/kaige8312/article/details/84826733