《springboot》springboot自定义starter

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

《springboot》springboot自定义starter_第1张图片

 

 

2.先查看源码

META-INF/spring.factories

《springboot》springboot自定义starter_第2张图片

《springboot》springboot自定义starter_第3张图片

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 {

    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

		
			org.springframework.boot
			spring-boot-configuration-processor
			true
		

		
			com.kevin
			springboot-log-starter
			0.0.1-SNAPSHOT
		

 

@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加入配置

	
       
		
			
				META-INF
				META-INF/
			
		
	

 

测试

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 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 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 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 factories = new ArrayList<>(new LinkedHashSet<>(
                SpringFactoriesLoader.loadFactoryNames(this.annotationClass, this.beanClassLoader)));
看这句 

SpringFactoriesLoader .java

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

		try {
			Enumeration 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《springboot》springboot自定义starter_第4张图片

测试如常.

你可能感兴趣的:(java,springboot,源码)