Table of Contents
1. Spring imports beans through annotations, which can be roughly divided into four ways. We mainly talk about the following two implementation methods of Import:
2. Springboot will be automatically assembled during startup
3. With TomcatServletWebServerFactory, it is equivalent to having the entrance for Spring loading.
Home Java javaTutorial How to use Tomcat container to achieve self-starting in springboot

How to use Tomcat container to achieve self-starting in springboot

May 12, 2023 am 10:25 AM
tomcat springboot

1. Spring imports beans through annotations, which can be roughly divided into four ways. We mainly talk about the following two implementation methods of Import:

1. Implement Bean loading by implementing the ImportSerlector interface:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

public class TestServiceImpl {

 public void testImpl() {

 System.out.println("我是通过importSelector导入进来的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";

 }

}

Copy after login

2. Implement Bean loading by implementing the ImportSerlector interface:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

public class TestService {

 public TestService() {

 System.out.println("我是通过ImportBeanDefinitionRegistrar导入进来的组件");

 }

}

public class TestImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

 @Override

 public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

 //定义一个BeanDefinition

 RootBeanDefinition beanDefinition = new RootBeanDefinition(TestService.class);

 //把自定义的bean定义导入到容器中

 registry.registerBeanDefinition("testService",beanDefinition);

 }

}

@Configuration

@Import(TestImportBeanDefinitionRegistrar.class)

public class TestConfig {

}

Copy after login

2. Springboot will be automatically assembled during startup

We start from spring-boot-autoconfigure-2.0.6.RELEASE I searched for the relevant configuration of Tomcat under .jar and found two automatic assembly classes, each containing three customizers (object-oriented single responsibility principle) and a factory class.

How to use Tomcat container to achieve self-starting in springboot

2.1. TomcatWebServerFactoryCustomizer: Customize Tomcat-specific functions common to Servlets and Reactive servers.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

public class TomcatWebServerFactoryCustomizer implements

 WebServerFactoryCustomizer<configurabletomcatwebserverfactory>, 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) -&gt; customizeMaxThreads(factory,

  tomcatProperties.getMaxThreads()));

 propertyMapper.from(tomcatProperties::getMinSpareThreads).when(this::isPositive)

 .to((minSpareThreads) -&gt; customizeMinThreads(factory, minSpareThreads));

 propertyMapper.from(() -&gt; determineMaxHttpHeaderSize()).when(this::isPositive)

 .to((maxHttpHeaderSize) -&gt; customizeMaxHttpHeaderSize(factory,

  maxHttpHeaderSize));

 propertyMapper.from(tomcatProperties::getMaxHttpPostSize)

 .when((maxHttpPostSize) -&gt; maxHttpPostSize != 0)

 .to((maxHttpPostSize) -&gt; customizeMaxHttpPostSize(factory,

  maxHttpPostSize));

 propertyMapper.from(tomcatProperties::getAccesslog)

 .when(ServerProperties.Tomcat.Accesslog::isEnabled)

 .to((enabled) -&gt; customizeAccessLog(factory));

 propertyMapper.from(tomcatProperties::getUriEncoding).whenNonNull()

 .to(factory::setUriEncoding);

 propertyMapper.from(properties::getConnectionTimeout).whenNonNull()

 .to((connectionTimeout) -&gt; customizeConnectionTimeout(factory,

  connectionTimeout));

 propertyMapper.from(tomcatProperties::getMaxConnections).when(this::isPositive)

 .to((maxConnections) -&gt; customizeMaxConnections(factory, maxConnections));

 propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive)

 .to((acceptCount) -&gt; customizeAcceptCount(factory, acceptCount));

 customizeStaticResources(factory);

 customizeErrorReportValve(properties.getError(), factory);

 }

}</configurabletomcatwebserverfactory>

Copy after login

2.2. ServletWebServerFactoryCustomizer: WebServerFactoryCustomizer applies the ServerProperties properties to the Tomcat web server.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

public class ServletWebServerFactoryCustomizer implements

 WebServerFactoryCustomizer<configurableservletwebserverfactory>, 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);

 }

}</configurableservletwebserverfactory>

Copy after login

2.3. ServletWebServerFactoryCustomizer: WebServerFactoryCustomizer applies ServerProperties properties to the Tomcat web server.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

public class TomcatServletWebServerFactoryCustomizer

 implements WebServerFactoryCustomizer<tomcatservletwebserverfactory>, 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());

 }

 }

}</tomcatservletwebserverfactory>

Copy after login

3. With TomcatServletWebServerFactory, it is equivalent to having the entrance for Spring loading.

Drive tomcat to start in the IOC container through AbstractApplicationContext#onReFresh(), and then execute other parts of the ioc container. step.

We can observe the entire life cycle of Tomcat loading through breakpoints, as well as the loading process of the three customizers.

How to use Tomcat container to achieve self-starting in springboot

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

@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);

 //设置是否自动启动

 tomcat.getHost().setAutoDeploy(false);

 //创建Tomcat引擎

 configureEngine(tomcat.getEngine());

 for (Connector additionalConnector : this.additionalTomcatConnectors) {

 tomcat.getService().addConnector(additionalConnector);

 }

 //刷新上下文

 prepareContext(tomcat.getHost(), initializers);

 //准备启动

 return getTomcatWebServer(tomcat);

}

Copy after login

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

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) -&gt; {

 if (context.equals(event.getSource())

  &amp;&amp; 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);

 }

 }

}

Copy after login

Note: In this process, we need to understand the life cycle of the Bean. Tomcat's three customizers are loaded in the BeanPostProcessorsRegistrar (Bean post-processor) process;

Constructor method-->Bean post-processorBefore-->InitializingBean-->init-method-->Bean post-processorAfter

1

2

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

  org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

Copy after login

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

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) {

 //构造方法

 instanceWrapper = createBeanInstance(beanName, mbd, args);

 }

 final Object bean = instanceWrapper.getWrappedInstance();

 Class&gt; 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<object>) () -&gt; {

 invokeAwareMethods(beanName, bean);

 return null;

 }, getAccessControlContext());

 }

 else {

 invokeAwareMethods(beanName, bean);

 }

 Object wrappedBean = bean;

 if (mbd == null || !mbd.isSynthetic()) {

 //Bean后置处理器Before

 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

 }

 try {

 invokeInitMethods(beanName, wrappedBean, mbd);

 }

 catch (Throwable ex) {

 throw new BeanCreationException(

 (mbd != null ? mbd.getResourceDescription() : null),

 beanName, "Invocation of init method failed", ex);

 }

 if (mbd == null || !mbd.isSynthetic()) {

 //Bean后置处理器After

 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

 }

 return wrappedBean;

}</object>

Copy after login

The above is the detailed content of How to use Tomcat container to achieve self-starting in springboot. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot Article Tags

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to deploy jar project in tomcat How to deploy jar project in tomcat Apr 21, 2024 am 07:27 AM

How to deploy jar project in tomcat

How to allow external network access to tomcat server How to allow external network access to tomcat server Apr 21, 2024 am 07:22 AM

How to allow external network access to tomcat server

How to deploy multiple projects in tomcat How to deploy multiple projects in tomcat Apr 21, 2024 am 09:33 AM

How to deploy multiple projects in tomcat

Where is the tomcat installation directory? Where is the tomcat installation directory? Apr 21, 2024 am 07:48 AM

Where is the tomcat installation directory?

Where is the root directory of the tomcat website? Where is the root directory of the tomcat website? Apr 21, 2024 am 09:27 AM

Where is the root directory of the tomcat website?

How to check the port number of tomcat How to check the port number of tomcat Apr 21, 2024 am 08:00 AM

How to check the port number of tomcat

How to check the number of concurrent connections in tomcat How to check the number of concurrent connections in tomcat Apr 21, 2024 am 08:12 AM

How to check the number of concurrent connections in tomcat

How to run two projects with different port numbers in tomcat How to run two projects with different port numbers in tomcat Apr 21, 2024 am 09:00 AM

How to run two projects with different port numbers in tomcat

See all articles