本篇文章給大家分享的是有關(guān)springboot中怎么利用Tomcat容器實(shí)現(xiàn)自啟動,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
創(chuàng)新互聯(lián)是專業(yè)的太和網(wǎng)站建設(shè)公司,太和接單;提供做網(wǎng)站、網(wǎng)站設(shè)計(jì),網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行太和網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!
1、通過實(shí)現(xiàn)ImportSerlector接口,實(shí)現(xiàn)Bean加載:
public class TestServiceImpl { public void testImpl() { System.out.println("我是通過importSelector導(dǎo)入進(jìn)來的service"); } } public class TestService implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"com.ycdhz.service.TestServiceImpl"}; } } @Configuration @Import(value = {TestService.class}) public class TestConfig { } public class TestController { @Autowired private TestServiceImpl testServiceImpl; @RequestMapping("testImpl") public String testTuling() { testServiceImpl.testImpl(); return "Ok"; } }
2、 通過實(shí)現(xiàn)ImportSerlector接口,實(shí)現(xiàn)Bean加載:
public class TestService { public TestService() { System.out.println("我是通過ImportBeanDefinitionRegistrar導(dǎo)入進(jìn)來的組件"); } } public class TestImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //定義一個(gè)BeanDefinition RootBeanDefinition beanDefinition = new RootBeanDefinition(TestService.class); //把自定義的bean定義導(dǎo)入到容器中 registry.registerBeanDefinition("testService",beanDefinition); } } @Configuration @Import(TestImportBeanDefinitionRegistrar.class) public class TestConfig { }
我們從spring-boot-autoconfigure-2.0.6.RELEASE.jar下搜索到Tomcat的相關(guān)配置,發(fā)現(xiàn)有兩個(gè)自動裝配類,分別包含了三個(gè)定制器(面向?qū)ο蟮膯我宦氊?zé)原則),還有一個(gè)工廠類。
2.1、TomcatWebServerFactoryCustomizer:定制Servlet和Reactive服務(wù)器通用的Tomcat特定功能。
public class TomcatWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { @Override public void customize(ConfigurableTomcatWebServerFactory factory) { ServerProperties properties = this.serverProperties; ServerProperties.Tomcat tomcatProperties = properties.getTomcat(); PropertyMapper propertyMapper = PropertyMapper.get(); propertyMapper.from(tomcatProperties::getBasedir).whenNonNull() .to(factory::setBaseDirectory); propertyMapper.from(tomcatProperties::getBackgroundProcessorDelay).whenNonNull() .as(Duration::getSeconds).as(Long::intValue) .to(factory::setBackgroundProcessorDelay); customizeRemoteIpValve(factory); propertyMapper.from(tomcatProperties::getMaxThreads).when(this::isPositive) .to((maxThreads) -> customizeMaxThreads(factory, tomcatProperties.getMaxThreads())); propertyMapper.from(tomcatProperties::getMinSpareThreads).when(this::isPositive) .to((minSpareThreads) -> customizeMinThreads(factory, minSpareThreads)); propertyMapper.from(() -> determineMaxHttpHeaderSize()).when(this::isPositive) .to((maxHttpHeaderSize) -> customizeMaxHttpHeaderSize(factory, maxHttpHeaderSize)); propertyMapper.from(tomcatProperties::getMaxHttpPostSize) .when((maxHttpPostSize) -> maxHttpPostSize != 0) .to((maxHttpPostSize) -> customizeMaxHttpPostSize(factory, maxHttpPostSize)); propertyMapper.from(tomcatProperties::getAccesslog) .when(ServerProperties.Tomcat.Accesslog::isEnabled) .to((enabled) -> customizeAccessLog(factory)); propertyMapper.from(tomcatProperties::getUriEncoding).whenNonNull() .to(factory::setUriEncoding); propertyMapper.from(properties::getConnectionTimeout).whenNonNull() .to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout)); propertyMapper.from(tomcatProperties::getMaxConnections).when(this::isPositive) .to((maxConnections) -> customizeMaxConnections(factory, maxConnections)); propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive) .to((acceptCount) -> customizeAcceptCount(factory, acceptCount)); customizeStaticResources(factory); customizeErrorReportValve(properties.getError(), factory); } }
2.2、ServletWebServerFactoryCustomizer:WebServerFactoryCustomizer 將ServerProperties屬性應(yīng)用于Tomcat web服務(wù)器。
public class ServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { private final ServerProperties serverProperties; public ServletWebServerFactoryCustomizer(ServerProperties serverProperties) { this.serverProperties = serverProperties; } @Override public int getOrder() { return 0; } @Override public void customize(ConfigurableServletWebServerFactory factory) { PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(this.serverProperties::getPort).to(factory::setPort); map.from(this.serverProperties::getAddress).to(factory::setAddress); map.from(this.serverProperties.getServlet()::getContextPath) .to(factory::setContextPath); map.from(this.serverProperties.getServlet()::getApplicationDisplayName) .to(factory::setDisplayName); map.from(this.serverProperties.getServlet()::getSession).to(factory::setSession); map.from(this.serverProperties::getSsl).to(factory::setSsl); map.from(this.serverProperties.getServlet()::getJsp).to(factory::setJsp); map.from(this.serverProperties::getCompression).to(factory::setCompression); map.from(this.serverProperties::getHttp2).to(factory::setHttp2); map.from(this.serverProperties::getServerHeader).to(factory::setServerHeader); map.from(this.serverProperties.getServlet()::getContextParameters) .to(factory::setInitParameters); } }
2.3、ServletWebServerFactoryCustomizer :WebServerFactoryCustomizer 將ServerProperties屬性應(yīng)用于Tomcat web服務(wù)器。
public class TomcatServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { private final ServerProperties serverProperties; public TomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) { this.serverProperties = serverProperties; } @Override public void customize(TomcatServletWebServerFactory factory) { ServerProperties.Tomcat tomcatProperties = this.serverProperties.getTomcat(); if (!ObjectUtils.isEmpty(tomcatProperties.getAdditionalTldSkipPatterns())) { factory.getTldSkipPatterns() .addAll(tomcatProperties.getAdditionalTldSkipPatterns()); } if (tomcatProperties.getRedirectContextRoot() != null) { customizeRedirectContextRoot(factory, tomcatProperties.getRedirectContextRoot()); } if (tomcatProperties.getUseRelativeRedirects() != null) { customizeUseRelativeRedirects(factory, tomcatProperties.getUseRelativeRedirects()); } } }
通過AbstractApplicationContext#onReFresh()在IOC 容器中的帶動tomcat啟動,然后在接著執(zhí)行 ioc容器的其他步驟。
我們通過斷點(diǎn)可以觀察Tomcat加載的整個(gè)生命周期,以及三個(gè)定制器的加載過程。
@Override public WebServer getWebServer(ServletContextInitializer... initializers) { Tomcat tomcat = new Tomcat(); File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat"); tomcat.setBaseDir(baseDir.getAbsolutePath()); Connector connector = new Connector(this.protocol); tomcat.getService().addConnector(connector); customizeConnector(connector); tomcat.setConnector(connector); //設(shè)置是否自動啟動 tomcat.getHost().setAutoDeploy(false); //創(chuàng)建Tomcat引擎 configureEngine(tomcat.getEngine()); for (Connector additionalConnector : this.additionalTomcatConnectors) { tomcat.getService().addConnector(additionalConnector); } //刷新上下文 prepareContext(tomcat.getHost(), initializers); //準(zhǔn)備啟動 return getTomcatWebServer(tomcat); }
private void initialize() throws WebServerException { TomcatWebServer.logger .info("Tomcat initialized with port(s): " + getPortsDescription(false)); synchronized (this.monitor) { try { addInstanceIdToEngineName(); Context context = findContext(); context.addLifecycleListener((event) -> { if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) { // Remove service connectors so that protocol binding doesn't // happen when the service is started. removeServiceConnectors(); } }); // Start the server to trigger initialization listeners this.tomcat.start(); // We can re-throw failure exception directly in the main thread rethrowDeferredStartupExceptions(); try { ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader()); } catch (NamingException ex) { // Naming is not enabled. Continue } // Unlike Jetty, all Tomcat threads are daemon threads. We create a // blocking non-daemon to stop immediate shutdown startDaemonAwaitThread(); } catch (Exception ex) { stopSilently(); throw new WebServerException("Unable to start embedded Tomcat", ex); } } }
備注: 在這個(gè)過程中我們需要了解Bean的生命周期,Tomcat的三個(gè)定制器均在BeanPostProcessorsRegistrar(Bean后置處理器)過程中加載;
構(gòu)造方法-->Bean后置處理器Before-->InitializingBean-->init-method-->Bean后置處理器After
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //構(gòu)造方法 instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Initialize the bean instance. ...... return exposedObject; } protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction
以上就是springboot中怎么利用Tomcat容器實(shí)現(xiàn)自啟動,小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。