咱們使用zuul的時候,就會用這個註解,這個主鍵的功能和Eureka Server同樣。import了ZuulProxyMarkerConfiguration類。spring
@EnableCircuitBreaker @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(ZuulProxyMarkerConfiguration.class) public @interface EnableZuulProxy { }
ZuulProxyMarkerConfiguration類的主要做用是加載了ZuulProxyMarkerConfiguration#Marker類。segmentfault
@Configuration(proxyBeanMethods = false) public class ZuulProxyMarkerConfiguration { @Bean public Marker zuulProxyMarkerBean() { return new Marker(); } class Marker { } }
咱們從spring.factories看,能夠看到他包括了ZuulServerAutoConfiguration和ZuulProxyAutoConfiguration,這兩個類能不能被加載,他的條件就是有沒有ZuulProxyMarkerConfiguration#Marker類。ide
這個類是ApplicationListener<ApplicationEvent>,當有ContextRefreshedEvent、RefreshScopeRefreshedEvent、RoutesRefreshedEvent、InstanceRegisteredEvent的時候,就會觸發重置,動態路由就是經過這個來實現的。ui
@Bean public ApplicationListener<ApplicationEvent> zuulRefreshRoutesListener() { return new ZuulRefreshListener(); }
建立ZuulServlet,這個是HttpServlet,初始化會調用init方法,在ZuulServlet#init方法中,會建立一個ZuulRunner對象。this
@Bean @ConditionalOnMissingBean(name = "zuulServlet") @ConditionalOnProperty(name = "zuul.use-filter", havingValue = "false", matchIfMissing = true) public ServletRegistrationBean zuulServlet() { ServletRegistrationBean<ZuulServlet> servlet = new ServletRegistrationBean<>( new ZuulServlet(), this.zuulProperties.getServletPattern()); // The whole point of exposing this servlet is to provide a route that doesn't // buffer requests. servlet.addInitParameter("buffer-requests", "false"); return servlet; }
與zuulServlet相似的是ZuulServletFilter,默認沒有加載。spa
咱們看過Ribbon - 懶加載就知道了,懶加載轉直接加載。code
@Bean @ConditionalOnProperty("zuul.ribbon.eager-load.enabled") public ZuulRouteApplicationContextInitializer zuulRoutesApplicationContextInitiazer( SpringClientFactory springClientFactory) { return new ZuulRouteApplicationContextInitializer(springClientFactory, zuulProperties); }
先獲取ZuulFilter,而後實例化ZuulFilterInitializer,他有個@PostConstruct註解,因此會調用ZuulFilterInitializer#contextInitialized方法。對象
@Configuration(proxyBeanMethods = false) protected static class ZuulFilterConfiguration { @Autowired private Map<String, ZuulFilter> filters; @Bean public ZuulFilterInitializer zuulFilterInitializer(CounterFactory counterFactory, TracerFactory tracerFactory) { FilterLoader filterLoader = FilterLoader.getInstance(); FilterRegistry filterRegistry = FilterRegistry.instance(); return new ZuulFilterInitializer(this.filters, counterFactory, tracerFactory, filterLoader, filterRegistry); } }
在這個方法中,比較重要的就是把ZuulFilter集合存入FilterRegistry的filters中。blog
@PostConstruct public void contextInitialized() { log.info("Starting filter initializer"); TracerFactory.initialize(tracerFactory); CounterFactory.initialize(counterFactory); for (Map.Entry<String, ZuulFilter> entry : this.filters.entrySet()) { filterRegistry.put(entry.getKey(), entry.getValue()); } }
因此zuul啓動的時候,就會把ZuulFilter集合存入FilterRegistry的filters中。路由