先来一个很普通的例子, springBoot创建自定义filter
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("加载进来了");
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
然后创建一个bean 将MyFilter注册到FilterRegistrationBean中
@Bean
public FilterRegistrationBean myFilter(){
FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean(new MyFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setName("myFilter");
return filterRegistrationBean;
}
然后随便访问一个路径,即可看到 “加载进来了” 打印信息
具体的实现过程网上有很多了,这里不再赘述
然后来一个非常规的简化写法,自定义filter保持不变,bean的写法改变如下
@Bean
public MyFilter myFilter(){
return new MyFilter();
}
再随便访问一个路径, 发现filter依然生效,显然是智能的springboot帮我们做了不少工作
这里简要的贴出相关源码 以做笔记
无论是通过 继承SpringBootServletInitializer 还是通过 SpringApplication.run() 的方式加载springboot, 都会初始化AnnotationConfigServletWebServerApplicationContext
其父类是ServletWebServerApplicationContext
@Override
//org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh
//最终会执行这段代码
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
//关键是这句,做一些初始化的工作
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context",
ex);
}
}
initPropertySources();
}
private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
return this::selfInitialize;
}
private void selfInitialize(ServletContext servletContext) throws ServletException {
prepareWebApplicationContext(servletContext);
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(
beanFactory);
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory,
getServletContext());
existingScopes.restore();
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory,
getServletContext());
//关键代码, 获取需要做初始化的bean进行处理
for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
beans.onStartup(servletContext);
}
}
//这个获取初始化bean的操作最终交给了ServletContextInitializerBeans处理
protected Collection<ServletContextInitializer> getServletContextInitializerBeans() {
return new ServletContextInitializerBeans(getBeanFactory());
}
接下来看ServletContextInitializerBeans 的重要代码
//可以看出,此类最终要输出 ServletContextInitializer的集合
//也就是说需要将相关的bean 包装成ServletContextInitializer的子类
//而刚好RegistrationBean也实现了ServletContextInitializer接口,似乎快水落石出了
public class ServletContextInitializerBeans
extends AbstractCollection<ServletContextInitializer>
//构造方法
public ServletContextInitializerBeans(ListableBeanFactory beanFactory) {
this.initializers = new LinkedMultiValueMap<>();
addServletContextInitializerBeans(beanFactory);
//重点看这里,使用适配的方式对beanFactory中的bean进行处理
addAdaptableBeans(beanFactory);
List<ServletContextInitializer> sortedInitializers = new ArrayList<>();
this.initializers.values().forEach((contextInitializers) -> {
AnnotationAwareOrderComparator.sort(contextInitializers);
sortedInitializers.addAll(contextInitializers);
});
this.sortedList = Collections.unmodifiableList(sortedInitializers);
}
private void addAdaptableBeans(ListableBeanFactory beanFactory) {
MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);
//获取bean中所有的Servlet类,创建ServletRegistrationBeanAdapter适配器进行处理
addAsRegistrationBean(beanFactory, Servlet.class,
new ServletRegistrationBeanAdapter(multipartConfig));
//同上 处理Filter
addAsRegistrationBean(beanFactory, Filter.class,
new FilterRegistrationBeanAdapter());
//处理相关的EventListener,具体查看ServletListenerRegistrationBean
for (Class<?> listenerType : ServletListenerRegistrationBean
.getSupportedTypes()) {
addAsRegistrationBean(beanFactory, EventListener.class,
(Class<EventListener>) listenerType,
new ServletListenerRegistrationBeanAdapter());
}
}
到这里基本可以结束了,通过以上源码可以了解
springBoot 会筛选出bean中的 filter、servlet、EventListener 对象,包装成相应的RegistrationBean进行处理
当然了里面的相关属性也是默认的,如果需要自定义 还是得自己创建RegistrationBean