1. 依赖导入
2. 过滤器定义
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...");
}
}
3. 将过滤器封装成Spring Bean
public class LogFilterRegistrationBean extends FilterRegistrationBean
public LogFilterRegistrationBean() {
super();
this.setFilter(new LogFilter());
this.addUrlPatterns("/*");
this.setName("LogFilter");
this.setOrder(1);
}
}
4. 定义自动配置类
@Configuration
@ConditionalOnClass({LogFilterRegistrationBean.class, LogFilter.class})
public class LogFilterAutoConfiguration {
@Bean
@ConditionalOnMissingBean(LogFilterRegistrationBean.class)
public LogFilterRegistrationBean logFilterRegistrationBean() {
return new LogFilterRegistrationBean();
}
}
5. 自动配置类生效
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableLogFilterImportSelector.class)
// 可直接引入LogFilterAutoConfiguration配置类
// 通过引入ImportSelector来获取spring.factories中需要加载的自动配置类
public @interface EnableLogFilter {
}
自定义注解的目的是使LogFilterAutoConfiguration配置类生效,自定义的starter中对应的classes并不在项目的spring扫描范围之内,故无法引入项目的spring管理之中。
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
.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
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;
}
}
6. 自动配置类
在resources/META-INF/spring.factories中增加相关配置com.XXX.EnableLogFilter=com.XXX.LogFilterAutoConfiguration
7. 自定义starter的使用
@SpringBootApplication
@EnableLogFilter
public class SpringbootDemoApplication{
public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}