一、何谓BeanProcessor

  BeanPostProcessor是SpringFramework里非常重要的核心接口之一,我先贴出一段源代码:

  1. /*
  2. * Copyright 2002-2015 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16.  
  17. package org.springframework.beans.factory.config;
  18.  
  19. import org.springframework.beans.BeansException;
  20.  
  21. /**
  22. * Factory hook that allows for custom modification of new bean instances,
  23. * e.g. checking for marker interfaces or wrapping them with proxies.
  24. *
  25. * <p>ApplicationContexts can autodetect BeanPostProcessor beans in their
  26. * bean definitions and apply them to any beans subsequently created.
  27. * Plain bean factories allow for programmatic registration of post-processors,
  28. * applying to all beans created through this factory.
  29. *
  30. * <p>Typically, post-processors that populate beans via marker interfaces
  31. * or the like will implement {@link #postProcessBeforeInitialization},
  32. * while post-processors that wrap beans with proxies will normally
  33. * implement {@link #postProcessAfterInitialization}.
  34. *
  35. * @author Juergen Hoeller
  36. * @since 10.10.2003
  37. * @see InstantiationAwareBeanPostProcessor
  38. * @see DestructionAwareBeanPostProcessor
  39. * @see ConfigurableBeanFactory#addBeanPostProcessor
  40. * @see BeanFactoryPostProcessor
  41. */
  42. public interface BeanPostProcessor {
  43.  
  44. /**
  45. * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
  46. * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
  47. * or a custom init-method). The bean will already be populated with property values.
  48. * The returned bean instance may be a wrapper around the original.
  49. * @param bean the new bean instance
  50. * @param beanName the name of the bean
  51. * @return the bean instance to use, either the original or a wrapped one;
  52. * if {@code null}, no subsequent BeanPostProcessors will be invoked
  53. * @throws org.springframework.beans.BeansException in case of errors
  54. * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
  55. */
  56. Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
  57.  
  58. /**
  59. * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
  60. * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
  61. * or a custom init-method). The bean will already be populated with property values.
  62. * The returned bean instance may be a wrapper around the original.
  63. * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
  64. * instance and the objects created by the FactoryBean (as of Spring 2.0). The
  65. * post-processor can decide whether to apply to either the FactoryBean or created
  66. * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
  67. * <p>This callback will also be invoked after a short-circuiting triggered by a
  68. * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
  69. * in contrast to all other BeanPostProcessor callbacks.
  70. * @param bean the new bean instance
  71. * @param beanName the name of the bean
  72. * @return the bean instance to use, either the original or a wrapped one;
  73. * if {@code null}, no subsequent BeanPostProcessors will be invoked
  74. * @throws org.springframework.beans.BeansException in case of errors
  75. * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
  76. * @see org.springframework.beans.factory.FactoryBean
  77. */
  78. Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
  79.  
  80. }

  在这里我先简单解释一下其注释的含义:

  这个接口允许我们自定义修改新bean的一个实例,比如说:检查它们的接口或者将他们包装成代理对象等,ApplicationContexts能自动察觉到我们在BeanProcessor里对对象作出的改变,并在后来创建该对象时应用其对应的改变。

  这两个方法分别对应IOC容器对对象初始化前的操作和对象初始化后的操作

  下面我们来演示一个例子:

  StudentEntity:

  1. package org.hzgj.spring.study.entity;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7.  
  8. public class StudentEntity {
  9.  
  10. private Integer id;
  11.  
  12. private String name;
  13.  
  14. private Map<String,String> memerories= new HashMap<>();
  15.  
  16. public Map<String, String> getMemerories() {
  17. return memerories;
  18. }
  19.  
  20. public void setMemerories(Map<String, String> memerories) {
  21. this.memerories = memerories;
  22. }
  23.  
  24. public Integer getId() {
  25. return id;
  26. }
  27.  
  28. public void setId(Integer id) {
  29. this.id = id;
  30. }
  31.  
  32. public String getName() {
  33. return name;
  34. }
  35.  
  36. public void setName(String name) {
  37. this.name = name;
  38. }
  39.  
  40. public StudentEntity() {
  41. // System.out.println("studentEntity initializer....");
  42. }
  43.  
  44. @Override
  45. public String toString() {
  46. return "StudentEntity{" +
  47. "id=" + id +
  48. ", name='" + name + '\'' +
  49. '}';
  50. }
  51.  
  52. private List<String> hobbies=new ArrayList<>();
  53.  
  54. public List<String> getHobbies() {
  55. return hobbies;
  56. }
  57.  
  58. public void setHobbies(List<String> hobbies) {
  59. this.hobbies = hobbies;
  60. }
  61. }

  

  TestBeanPostProcessor:

  1. package org.hzgj.spring.study.context;
  2.  
  3. import org.hzgj.spring.study.entity.StudentEntity;
  4. import org.springframework.beans.BeansException;
  5. import org.springframework.beans.factory.config.BeanPostProcessor;
  6.  
  7. public class TestBeanPostProcessor implements BeanPostProcessor {
  8.  
  9. @Override
  10. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  11. if (bean instanceof StudentEntity) {
  12. StudentEntity studentEntity = new StudentEntity();
  13. studentEntity.setName(beanName);
  14. return studentEntity;
  15. }
  16. return bean;
  17. }
  18.  
  19. @Override
  20. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  21. if (bean instanceof StudentEntity)
  22. System.out.println(bean);
  23. return bean;
  24. }
  25. }

  Main方法:

  1. package org.hzgj.spring.study;
  2.  
  3. import org.hzgj.spring.study.entity.StudentEntity;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5.  
  6. public class Main {
  7. public static void main(String[] args) {
  8. ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-config.xml");
  9. StudentEntity studentEntity = applicationContext.getBean(StudentEntity.class);
  10. System.out.println(studentEntity.getName());
  11.  
  12. }
  13. }

  

  spring-config.xml关键代码:

  1. <bean id="studentEntity" class="org.hzgj.spring.study.entity.StudentEntity" depends-on="studentServiceWithFactory">
  2. <property name="hobbies" ref="hobbies">
  3. </property>
  4. <property name="memerories">
  5. <map>
  6. <entry key="glad" value="play"/>
  7. <entry key="cry" value="cry"/>
  8. </map>
  9. </property>
  10. <property name="name" value="admin"/>
  11. </bean>
  12.  
  13. <bean id="beanPostProcessor" class="org.hzgj.spring.study.context.TestBeanPostProcessor" />

  运行得到如下结果:

  我们可以看到在配置文件里定义的bean属性已经发生改变

二、SpringFramework中BeanPostProcessor经典应用场景

1.初始化BeanPostProcessor的源码

根据 ClassPathXmlApplicationContext的构造方法,我们可以看到该类初始化的时候会调用refresh():

  1. /**
  2. * Create a new ClassPathXmlApplicationContext with the given parent,
  3. * loading the definitions from the given XML files.
  4. * @param configLocations array of resource locations
  5. * @param refresh whether to automatically refresh the context,
  6. * loading all bean definitions and creating all singletons.
  7. * Alternatively, call refresh manually after further configuring the context.
  8. * @param parent the parent context
  9. * @throws BeansException if context creation failed
  10. * @see #refresh()
  11. */
  12. public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
  13. throws BeansException {
  14.  
  15. super(parent);
  16. setConfigLocations(configLocations);
  17. if (refresh) {
  18. refresh();
  19. }
  20. }

那么紧接着在AbstractApplicationContext中找到refresh()方法:

  1. @Override
  2. public void refresh() throws BeansException, IllegalStateException {
  3. synchronized (this.startupShutdownMonitor) {
  4. // Prepare this context for refreshing.
  5. prepareRefresh();
  6.  
  7. // Tell the subclass to refresh the internal bean factory.
  8. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  9.  
  10. // Prepare the bean factory for use in this context.
  11. prepareBeanFactory(beanFactory);
  12.  
  13. try {
  14. // Allows post-processing of the bean factory in context subclasses.
  15. postProcessBeanFactory(beanFactory);
  16.  
  17. // Invoke factory processors registered as beans in the context.
  18. invokeBeanFactoryPostProcessors(beanFactory);
  19.  
  20. // Register bean processors that intercept bean creation.
  21. registerBeanPostProcessors(beanFactory);
  22.  
  23. // Initialize message source for this context.
  24. initMessageSource();
  25.  
  26. // Initialize event multicaster for this context.
  27. initApplicationEventMulticaster();
  28.  
  29. // Initialize other special beans in specific context subclasses.
  30. onRefresh();
  31.  
  32. // Check for listener beans and register them.
  33. registerListeners();
  34.  
  35. // Instantiate all remaining (non-lazy-init) singletons.
  36. finishBeanFactoryInitialization(beanFactory);
  37.  
  38. // Last step: publish corresponding event.
  39. finishRefresh();
  40. }
  41.  
  42. catch (BeansException ex) {
  43. if (logger.isWarnEnabled()) {
  44. logger.warn("Exception encountered during context initialization - " +
  45. "cancelling refresh attempt: " + ex);
  46. }
  47.  
  48. // Destroy already created singletons to avoid dangling resources.
  49. destroyBeans();
  50.  
  51. // Reset 'active' flag.
  52. cancelRefresh(ex);
  53.  
  54. // Propagate exception to caller.
  55. throw ex;
  56. }
  57.  
  58. finally {
  59. // Reset common introspection caches in Spring's core, since we
  60. // might not ever need metadata for singleton beans anymore...
  61. resetCommonCaches();
  62. }
  63. }
  64. }

那么在这里Spring会进行一系列的初始化操作,我们请留意registerBeanPostProcessors(beanFactory);这句代码,追踪一下我们可以看到在该方法里注册Processor:

  1. public static void registerBeanPostProcessors(
  2. ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
  3.  
  4. String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
  5.  
  6. // Register BeanPostProcessorChecker that logs an info message when
  7. // a bean is created during BeanPostProcessor instantiation, i.e. when
  8. // a bean is not eligible for getting processed by all BeanPostProcessors.
  9. int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
  10. beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
  11.  
  12. // Separate between BeanPostProcessors that implement PriorityOrdered,
  13. // Ordered, and the rest.
  14. List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
  15. List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
  16. List<String> orderedPostProcessorNames = new ArrayList<String>();
  17. List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
  18. for (String ppName : postProcessorNames) {
  19. if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
  20. BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
  21. priorityOrderedPostProcessors.add(pp);
  22. if (pp instanceof MergedBeanDefinitionPostProcessor) {
  23. internalPostProcessors.add(pp);
  24. }
  25. }
  26. else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
  27. orderedPostProcessorNames.add(ppName);
  28. }
  29. else {
  30. nonOrderedPostProcessorNames.add(ppName);
  31. }
  32. }
  33.  
  34. // First, register the BeanPostProcessors that implement PriorityOrdered.
  35. sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
  36. registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
  37.  
  38. // Next, register the BeanPostProcessors that implement Ordered.
  39. List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
  40. for (String ppName : orderedPostProcessorNames) {
  41. BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
  42. orderedPostProcessors.add(pp);
  43. if (pp instanceof MergedBeanDefinitionPostProcessor) {
  44. internalPostProcessors.add(pp);
  45. }
  46. }
  47. sortPostProcessors(orderedPostProcessors, beanFactory);
  48. registerBeanPostProcessors(beanFactory, orderedPostProcessors);
  49.  
  50. // Now, register all regular BeanPostProcessors.
  51. List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
  52. for (String ppName : nonOrderedPostProcessorNames) {
  53. BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
  54. nonOrderedPostProcessors.add(pp);
  55. if (pp instanceof MergedBeanDefinitionPostProcessor) {
  56. internalPostProcessors.add(pp);
  57. }
  58. }
  59. registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
  60.  
  61. // Finally, re-register all internal BeanPostProcessors.
  62. sortPostProcessors(internalPostProcessors, beanFactory);
  63. registerBeanPostProcessors(beanFactory, internalPostProcessors);
  64.  
  65. // Re-register post-processor for detecting inner beans as ApplicationListeners,
  66. // moving it to the end of the processor chain (for picking up proxies etc).
  67. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
  68. }

2.@Autowired实现的代码跟踪

注意AutowiredAnnotationBeanPostProcessor最终也是BeanPostProcessor的实现类,具体类的描述我就不再这里阐述了,大家可自行查看源码

3、SpringBoot中的定制化内嵌web容器

这个EmbeddedServletContainerCustomizerBeanPostProcessor直接实现的就是BeanPostProcessor,该类下请关注如下方法:

  1. @Override
  2. public Object postProcessBeforeInitialization(Object bean, String beanName)
  3. throws BeansException {
  4. if (bean instanceof ConfigurableEmbeddedServletContainer) {
  5. postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);
  6. }
  7. return bean;
  8. }
  1. private void postProcessBeforeInitialization(
  2. ConfigurableEmbeddedServletContainer bean) {
  3. for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {
  4. customizer.customize(bean);
  5. }
  6. }
  1. private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
  2. if (this.customizers == null) {
  3. // Look up does not include the parent context
  4. this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>(
  5. this.beanFactory
  6. .getBeansOfType(EmbeddedServletContainerCustomizer.class,
  7. false, false)
  8. .values());
  9. Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
  10. this.customizers = Collections.unmodifiableList(this.customizers);
  11. }
  12. return this.customizers;
  13. }

这里面有一个接口:EmbeddedServletContainerCustomizer 该接口有个实现类 ServerProperties 熟悉springboot外部化配置原理的同胞们其实一看便知

  1. /*
  2. * Copyright 2012-2018 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16.  
  17. package org.springframework.boot.autoconfigure.web;
  18.  
  19. import java.io.File;
  20. import java.net.InetAddress;
  21. import java.nio.charset.Charset;
  22. import java.util.ArrayList;
  23. import java.util.Collection;
  24. import java.util.HashMap;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.Set;
  28.  
  29. import javax.servlet.ServletContext;
  30. import javax.servlet.ServletException;
  31. import javax.servlet.SessionCookieConfig;
  32. import javax.servlet.SessionTrackingMode;
  33.  
  34. import io.undertow.Undertow.Builder;
  35. import io.undertow.UndertowOptions;
  36. import org.apache.catalina.Context;
  37. import org.apache.catalina.connector.Connector;
  38. import org.apache.catalina.valves.AccessLogValve;
  39. import org.apache.catalina.valves.ErrorReportValve;
  40. import org.apache.catalina.valves.RemoteIpValve;
  41. import org.apache.coyote.AbstractProtocol;
  42. import org.apache.coyote.ProtocolHandler;
  43. import org.apache.coyote.http11.AbstractHttp11Protocol;
  44. import org.eclipse.jetty.server.AbstractConnector;
  45. import org.eclipse.jetty.server.ConnectionFactory;
  46. import org.eclipse.jetty.server.Handler;
  47. import org.eclipse.jetty.server.HttpConfiguration;
  48. import org.eclipse.jetty.server.Server;
  49. import org.eclipse.jetty.server.handler.ContextHandler;
  50. import org.eclipse.jetty.server.handler.HandlerCollection;
  51. import org.eclipse.jetty.server.handler.HandlerWrapper;
  52.  
  53. import org.springframework.boot.autoconfigure.web.ServerProperties.Session.Cookie;
  54. import org.springframework.boot.cloud.CloudPlatform;
  55. import org.springframework.boot.context.embedded.Compression;
  56. import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
  57. import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
  58. import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
  59. import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
  60. import org.springframework.boot.context.embedded.InitParameterConfiguringServletContextInitializer;
  61. import org.springframework.boot.context.embedded.JspServlet;
  62. import org.springframework.boot.context.embedded.Ssl;
  63. import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
  64. import org.springframework.boot.context.embedded.jetty.JettyServerCustomizer;
  65. import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
  66. import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
  67. import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
  68. import org.springframework.boot.context.embedded.undertow.UndertowBuilderCustomizer;
  69. import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
  70. import org.springframework.boot.context.properties.ConfigurationProperties;
  71. import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
  72. import org.springframework.boot.context.properties.NestedConfigurationProperty;
  73. import org.springframework.boot.web.servlet.ServletContextInitializer;
  74. import org.springframework.context.EnvironmentAware;
  75. import org.springframework.core.Ordered;
  76. import org.springframework.core.env.Environment;
  77. import org.springframework.util.Assert;
  78. import org.springframework.util.ObjectUtils;
  79. import org.springframework.util.StringUtils;
  80.  
  81. /**
  82. * {@link ConfigurationProperties} for a web server (e.g. port and path settings). Will be
  83. * used to customize an {@link EmbeddedServletContainerFactory} when an
  84. * {@link EmbeddedServletContainerCustomizerBeanPostProcessor} is active.
  85. *
  86. * @author Dave Syer
  87. * @author Stephane Nicoll
  88. * @author Andy Wilkinson
  89. * @author Ivan Sopov
  90. * @author Marcos Barbero
  91. * @author Eddú Meléndez
  92. * @author Quinten De Swaef
  93. * @author Venil Noronha
  94. * @author Aurélien Leboulanger
  95. */
  96. @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
  97. public class ServerProperties
  98. implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered {
  99.  
  100. /**
  101. * Server HTTP port.
  102. */
  103. private Integer port;
  104.  
  105. /**
  106. * Network address to which the server should bind to.
  107. */
  108. private InetAddress address;
  109.  
  110. /**
  111. * Context path of the application.
  112. */
  113. private String contextPath;
  114.  
  115. /**
  116. * Display name of the application.
  117. */
  118. private String displayName = "application";
  119.  
  120. @NestedConfigurationProperty
  121. private ErrorProperties error = new ErrorProperties();
  122.  
  123. /**
  124. * Path of the main dispatcher servlet.
  125. */
  126. private String servletPath = "/";
  127.  
  128. /**
  129. * ServletContext parameters.
  130. */
  131. private final Map<String, String> contextParameters = new HashMap<String, String>();
  132.  
  133. /**
  134. * If X-Forwarded-* headers should be applied to the HttpRequest.
  135. */
  136. private Boolean useForwardHeaders;
  137.  
  138. /**
  139. * Value to use for the Server response header (no header is sent if empty).
  140. */
  141. private String serverHeader;
  142.  
  143. /**
  144. * Maximum size in bytes of the HTTP message header.
  145. */
  146. private int maxHttpHeaderSize = 0; // bytes
  147.  
  148. /**
  149. * Maximum size in bytes of the HTTP post content.
  150. */
  151. private int maxHttpPostSize = 0; // bytes
  152.  
  153. /**
  154. * Time in milliseconds that connectors will wait for another HTTP request before
  155. * closing the connection. When not set, the connector's container-specific default
  156. * will be used. Use a value of -1 to indicate no (i.e. infinite) timeout.
  157. */
  158. private Integer connectionTimeout;
  159.  
  160. private Session session = new Session();
  161.  
  162. @NestedConfigurationProperty
  163. private Ssl ssl;
  164.  
  165. @NestedConfigurationProperty
  166. private Compression compression = new Compression();
  167.  
  168. @NestedConfigurationProperty
  169. private JspServlet jspServlet;
  170.  
  171. private final Tomcat tomcat = new Tomcat();
  172.  
  173. private final Jetty jetty = new Jetty();
  174.  
  175. private final Undertow undertow = new Undertow();
  176.  
  177. private Environment environment;
  178.  
  179. @Override
  180. public int getOrder() {
  181. return 0;
  182. }
  183.  
  184. @Override
  185. public void setEnvironment(Environment environment) {
  186. this.environment = environment;
  187. }
  188.  
  189. @Override
  190. public void customize(ConfigurableEmbeddedServletContainer container) {
  191. if (getPort() != null) {
  192. container.setPort(getPort());
  193. }
  194. if (getAddress() != null) {
  195. container.setAddress(getAddress());
  196. }
  197. if (getContextPath() != null) {
  198. container.setContextPath(getContextPath());
  199. }
  200. if (getDisplayName() != null) {
  201. container.setDisplayName(getDisplayName());
  202. }
  203. if (getSession().getTimeout() != null) {
  204. container.setSessionTimeout(getSession().getTimeout());
  205. }
  206. container.setPersistSession(getSession().isPersistent());
  207. container.setSessionStoreDir(getSession().getStoreDir());
  208. if (getSsl() != null) {
  209. container.setSsl(getSsl());
  210. }
  211. if (getJspServlet() != null) {
  212. container.setJspServlet(getJspServlet());
  213. }
  214. if (getCompression() != null) {
  215. container.setCompression(getCompression());
  216. }
  217. container.setServerHeader(getServerHeader());
  218. if (container instanceof TomcatEmbeddedServletContainerFactory) {
  219. getTomcat().customizeTomcat(this,
  220. (TomcatEmbeddedServletContainerFactory) container);
  221. }
  222. if (container instanceof JettyEmbeddedServletContainerFactory) {
  223. getJetty().customizeJetty(this,
  224. (JettyEmbeddedServletContainerFactory) container);
  225. }
  226.  
  227. if (container instanceof UndertowEmbeddedServletContainerFactory) {
  228. getUndertow().customizeUndertow(this,
  229. (UndertowEmbeddedServletContainerFactory) container);
  230. }
  231. container.addInitializers(new SessionConfiguringInitializer(this.session));
  232. container.addInitializers(new InitParameterConfiguringServletContextInitializer(
  233. getContextParameters()));
  234. }
  235.  
  236. public String getServletMapping() {
  237. if (this.servletPath.equals("") || this.servletPath.equals("/")) {
  238. return "/";
  239. }
  240. if (this.servletPath.contains("*")) {
  241. return this.servletPath;
  242. }
  243. if (this.servletPath.endsWith("/")) {
  244. return this.servletPath + "*";
  245. }
  246. return this.servletPath + "/*";
  247. }
  248.  
  249. public String getPath(String path) {
  250. String prefix = getServletPrefix();
  251. if (!path.startsWith("/")) {
  252. path = "/" + path;
  253. }
  254. return prefix + path;
  255. }
  256.  
  257. public String getServletPrefix() {
  258. String result = this.servletPath;
  259. if (result.contains("*")) {
  260. result = result.substring(0, result.indexOf("*"));
  261. }
  262. if (result.endsWith("/")) {
  263. result = result.substring(0, result.length() - 1);
  264. }
  265. return result;
  266. }
  267.  
  268. public String[] getPathsArray(Collection<String> paths) {
  269. String[] result = new String[paths.size()];
  270. int i = 0;
  271. for (String path : paths) {
  272. result[i++] = getPath(path);
  273. }
  274. return result;
  275. }
  276.  
  277. public String[] getPathsArray(String[] paths) {
  278. String[] result = new String[paths.length];
  279. int i = 0;
  280. for (String path : paths) {
  281. result[i++] = getPath(path);
  282. }
  283. return result;
  284. }
  285.  
  286. public void setLoader(String value) {
  287. // no op to support Tomcat running as a traditional container (not embedded)
  288. }
  289.  
  290. public Integer getPort() {
  291. return this.port;
  292. }
  293.  
  294. public void setPort(Integer port) {
  295. this.port = port;
  296. }
  297.  
  298. public InetAddress getAddress() {
  299. return this.address;
  300. }
  301.  
  302. public void setAddress(InetAddress address) {
  303. this.address = address;
  304. }
  305.  
  306. public String getContextPath() {
  307. return this.contextPath;
  308. }
  309.  
  310. public void setContextPath(String contextPath) {
  311. this.contextPath = cleanContextPath(contextPath);
  312. }
  313.  
  314. private String cleanContextPath(String contextPath) {
  315. if (StringUtils.hasText(contextPath) && contextPath.endsWith("/")) {
  316. return contextPath.substring(0, contextPath.length() - 1);
  317. }
  318. return contextPath;
  319. }
  320.  
  321. public String getDisplayName() {
  322. return this.displayName;
  323. }
  324.  
  325. public void setDisplayName(String displayName) {
  326. this.displayName = displayName;
  327. }
  328.  
  329. public String getServletPath() {
  330. return this.servletPath;
  331. }
  332.  
  333. public void setServletPath(String servletPath) {
  334. Assert.notNull(servletPath, "ServletPath must not be null");
  335. this.servletPath = servletPath;
  336. }
  337.  
  338. public Map<String, String> getContextParameters() {
  339. return this.contextParameters;
  340. }
  341.  
  342. public Boolean isUseForwardHeaders() {
  343. return this.useForwardHeaders;
  344. }
  345.  
  346. public void setUseForwardHeaders(Boolean useForwardHeaders) {
  347. this.useForwardHeaders = useForwardHeaders;
  348. }
  349.  
  350. public String getServerHeader() {
  351. return this.serverHeader;
  352. }
  353.  
  354. public void setServerHeader(String serverHeader) {
  355. this.serverHeader = serverHeader;
  356. }
  357.  
  358. public int getMaxHttpHeaderSize() {
  359. return this.maxHttpHeaderSize;
  360. }
  361.  
  362. public void setMaxHttpHeaderSize(int maxHttpHeaderSize) {
  363. this.maxHttpHeaderSize = maxHttpHeaderSize;
  364. }
  365.  
  366. @Deprecated
  367. @DeprecatedConfigurationProperty(reason = "Use dedicated property for each container.")
  368. public int getMaxHttpPostSize() {
  369. return this.maxHttpPostSize;
  370. }
  371.  
  372. @Deprecated
  373. public void setMaxHttpPostSize(int maxHttpPostSize) {
  374. this.maxHttpPostSize = maxHttpPostSize;
  375. this.jetty.setMaxHttpPostSize(maxHttpPostSize);
  376. this.tomcat.setMaxHttpPostSize(maxHttpPostSize);
  377. this.undertow.setMaxHttpPostSize(maxHttpPostSize);
  378. }
  379.  
  380. protected final boolean getOrDeduceUseForwardHeaders() {
  381. if (this.useForwardHeaders != null) {
  382. return this.useForwardHeaders;
  383. }
  384. CloudPlatform platform = CloudPlatform.getActive(this.environment);
  385. return (platform == null ? false : platform.isUsingForwardHeaders());
  386. }
  387.  
  388. public Integer getConnectionTimeout() {
  389. return this.connectionTimeout;
  390. }
  391.  
  392. public void setConnectionTimeout(Integer connectionTimeout) {
  393. this.connectionTimeout = connectionTimeout;
  394. }
  395.  
  396. public ErrorProperties getError() {
  397. return this.error;
  398. }
  399.  
  400. public Session getSession() {
  401. return this.session;
  402. }
  403.  
  404. public void setSession(Session session) {
  405. this.session = session;
  406. }
  407.  
  408. public Ssl getSsl() {
  409. return this.ssl;
  410. }
  411.  
  412. public void setSsl(Ssl ssl) {
  413. this.ssl = ssl;
  414. }
  415.  
  416. public Compression getCompression() {
  417. return this.compression;
  418. }
  419.  
  420. public JspServlet getJspServlet() {
  421. return this.jspServlet;
  422. }
  423.  
  424. public void setJspServlet(JspServlet jspServlet) {
  425. this.jspServlet = jspServlet;
  426. }
  427.  
  428. public Tomcat getTomcat() {
  429. return this.tomcat;
  430. }
  431.  
  432. public Jetty getJetty() {
  433. return this.jetty;
  434. }
  435.  
  436. public Undertow getUndertow() {
  437. return this.undertow;
  438. }
  439.  
  440. public static class Session {
  441.  
  442. /**
  443. * Session timeout in seconds.
  444. */
  445. private Integer timeout;
  446.  
  447. /**
  448. * Session tracking modes (one or more of the following: "cookie", "url", "ssl").
  449. */
  450. private Set<SessionTrackingMode> trackingModes;
  451.  
  452. /**
  453. * Persist session data between restarts.
  454. */
  455. private boolean persistent;
  456.  
  457. /**
  458. * Directory used to store session data.
  459. */
  460. private File storeDir;
  461.  
  462. private Cookie cookie = new Cookie();
  463.  
  464. public Cookie getCookie() {
  465. return this.cookie;
  466. }
  467.  
  468. public Integer getTimeout() {
  469. return this.timeout;
  470. }
  471.  
  472. public void setTimeout(Integer sessionTimeout) {
  473. this.timeout = sessionTimeout;
  474. }
  475.  
  476. public Set<SessionTrackingMode> getTrackingModes() {
  477. return this.trackingModes;
  478. }
  479.  
  480. public void setTrackingModes(Set<SessionTrackingMode> trackingModes) {
  481. this.trackingModes = trackingModes;
  482. }
  483.  
  484. public boolean isPersistent() {
  485. return this.persistent;
  486. }
  487.  
  488. public void setPersistent(boolean persistent) {
  489. this.persistent = persistent;
  490. }
  491.  
  492. public File getStoreDir() {
  493. return this.storeDir;
  494. }
  495.  
  496. public void setStoreDir(File storeDir) {
  497. this.storeDir = storeDir;
  498. }
  499.  
  500. public static class Cookie {
  501.  
  502. /**
  503. * Session cookie name.
  504. */
  505. private String name;
  506.  
  507. /**
  508. * Domain for the session cookie.
  509. */
  510. private String domain;
  511.  
  512. /**
  513. * Path of the session cookie.
  514. */
  515. private String path;
  516.  
  517. /**
  518. * Comment for the session cookie.
  519. */
  520. private String comment;
  521.  
  522. /**
  523. * "HttpOnly" flag for the session cookie.
  524. */
  525. private Boolean httpOnly;
  526.  
  527. /**
  528. * "Secure" flag for the session cookie.
  529. */
  530. private Boolean secure;
  531.  
  532. /**
  533. * Maximum age of the session cookie in seconds.
  534. */
  535. private Integer maxAge;
  536.  
  537. public String getName() {
  538. return this.name;
  539. }
  540.  
  541. public void setName(String name) {
  542. this.name = name;
  543. }
  544.  
  545. public String getDomain() {
  546. return this.domain;
  547. }
  548.  
  549. public void setDomain(String domain) {
  550. this.domain = domain;
  551. }
  552.  
  553. public String getPath() {
  554. return this.path;
  555. }
  556.  
  557. public void setPath(String path) {
  558. this.path = path;
  559. }
  560.  
  561. public String getComment() {
  562. return this.comment;
  563. }
  564.  
  565. public void setComment(String comment) {
  566. this.comment = comment;
  567. }
  568.  
  569. public Boolean getHttpOnly() {
  570. return this.httpOnly;
  571. }
  572.  
  573. public void setHttpOnly(Boolean httpOnly) {
  574. this.httpOnly = httpOnly;
  575. }
  576.  
  577. public Boolean getSecure() {
  578. return this.secure;
  579. }
  580.  
  581. public void setSecure(Boolean secure) {
  582. this.secure = secure;
  583. }
  584.  
  585. public Integer getMaxAge() {
  586. return this.maxAge;
  587. }
  588.  
  589. public void setMaxAge(Integer maxAge) {
  590. this.maxAge = maxAge;
  591. }
  592.  
  593. }
  594.  
  595. }
  596.  
  597. public static class Tomcat {
  598.  
  599. /**
  600. * Access log configuration.
  601. */
  602. private final Accesslog accesslog = new Accesslog();
  603.  
  604. /**
  605. * Regular expression that matches proxies that are to be trusted.
  606. */
  607. private String internalProxies = "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" // 10/8
  608. + "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" // 192.168/16
  609. + "169\\.254\\.\\d{1,3}\\.\\d{1,3}|" // 169.254/16
  610. + "127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" // 127/8
  611. + "172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" // 172.16/12
  612. + "172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|"
  613. + "172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}";
  614.  
  615. /**
  616. * Header that holds the incoming protocol, usually named "X-Forwarded-Proto".
  617. */
  618. private String protocolHeader;
  619.  
  620. /**
  621. * Value of the protocol header that indicates that the incoming request uses SSL.
  622. */
  623. private String protocolHeaderHttpsValue = "https";
  624.  
  625. /**
  626. * Name of the HTTP header used to override the original port value.
  627. */
  628. private String portHeader = "X-Forwarded-Port";
  629.  
  630. /**
  631. * Name of the http header from which the remote ip is extracted..
  632. */
  633. private String remoteIpHeader;
  634.  
  635. /**
  636. * Tomcat base directory. If not specified a temporary directory will be used.
  637. */
  638. private File basedir;
  639.  
  640. /**
  641. * Delay in seconds between the invocation of backgroundProcess methods.
  642. */
  643. private int backgroundProcessorDelay = 30; // seconds
  644.  
  645. /**
  646. * Maximum amount of worker threads.
  647. */
  648. private int maxThreads = 0; // Number of threads in protocol handler
  649.  
  650. /**
  651. * Minimum amount of worker threads.
  652. */
  653. private int minSpareThreads = 0; // Minimum spare threads in protocol handler
  654.  
  655. /**
  656. * Maximum size in bytes of the HTTP post content.
  657. */
  658. private int maxHttpPostSize = 0; // bytes
  659.  
  660. /**
  661. * Maximum size in bytes of the HTTP message header.
  662. */
  663. private int maxHttpHeaderSize = 0; // bytes
  664.  
  665. /**
  666. * Whether requests to the context root should be redirected by appending a / to
  667. * the path.
  668. */
  669. private Boolean redirectContextRoot;
  670.  
  671. /**
  672. * Character encoding to use to decode the URI.
  673. */
  674. private Charset uriEncoding;
  675.  
  676. /**
  677. * Maximum number of connections that the server will accept and process at any
  678. * given time. Once the limit has been reached, the operating system may still
  679. * accept connections based on the "acceptCount" property.
  680. */
  681. private int maxConnections = 0;
  682.  
  683. /**
  684. * Maximum queue length for incoming connection requests when all possible request
  685. * processing threads are in use.
  686. */
  687. private int acceptCount = 0;
  688.  
  689. /**
  690. * Comma-separated list of additional patterns that match jars to ignore for TLD
  691. * scanning. The special '?' and '*' characters can be used in the pattern to
  692. * match one and only one character and zero or more characters respectively.
  693. */
  694. private List<String> additionalTldSkipPatterns = new ArrayList<String>();
  695.  
  696. public int getMaxThreads() {
  697. return this.maxThreads;
  698. }
  699.  
  700. public void setMaxThreads(int maxThreads) {
  701. this.maxThreads = maxThreads;
  702. }
  703.  
  704. public int getMinSpareThreads() {
  705. return this.minSpareThreads;
  706. }
  707.  
  708. public void setMinSpareThreads(int minSpareThreads) {
  709. this.minSpareThreads = minSpareThreads;
  710. }
  711.  
  712. public int getMaxHttpPostSize() {
  713. return this.maxHttpPostSize;
  714. }
  715.  
  716. public void setMaxHttpPostSize(int maxHttpPostSize) {
  717. this.maxHttpPostSize = maxHttpPostSize;
  718. }
  719.  
  720. public Accesslog getAccesslog() {
  721. return this.accesslog;
  722. }
  723.  
  724. public int getBackgroundProcessorDelay() {
  725. return this.backgroundProcessorDelay;
  726. }
  727.  
  728. public void setBackgroundProcessorDelay(int backgroundProcessorDelay) {
  729. this.backgroundProcessorDelay = backgroundProcessorDelay;
  730. }
  731.  
  732. public File getBasedir() {
  733. return this.basedir;
  734. }
  735.  
  736. public void setBasedir(File basedir) {
  737. this.basedir = basedir;
  738. }
  739.  
  740. public String getInternalProxies() {
  741. return this.internalProxies;
  742. }
  743.  
  744. public void setInternalProxies(String internalProxies) {
  745. this.internalProxies = internalProxies;
  746. }
  747.  
  748. public String getProtocolHeader() {
  749. return this.protocolHeader;
  750. }
  751.  
  752. public void setProtocolHeader(String protocolHeader) {
  753. this.protocolHeader = protocolHeader;
  754. }
  755.  
  756. public String getProtocolHeaderHttpsValue() {
  757. return this.protocolHeaderHttpsValue;
  758. }
  759.  
  760. public void setProtocolHeaderHttpsValue(String protocolHeaderHttpsValue) {
  761. this.protocolHeaderHttpsValue = protocolHeaderHttpsValue;
  762. }
  763.  
  764. public String getPortHeader() {
  765. return this.portHeader;
  766. }
  767.  
  768. public void setPortHeader(String portHeader) {
  769. this.portHeader = portHeader;
  770. }
  771.  
  772. public Boolean getRedirectContextRoot() {
  773. return this.redirectContextRoot;
  774. }
  775.  
  776. public void setRedirectContextRoot(Boolean redirectContextRoot) {
  777. this.redirectContextRoot = redirectContextRoot;
  778. }
  779.  
  780. public String getRemoteIpHeader() {
  781. return this.remoteIpHeader;
  782. }
  783.  
  784. public void setRemoteIpHeader(String remoteIpHeader) {
  785. this.remoteIpHeader = remoteIpHeader;
  786. }
  787.  
  788. public Charset getUriEncoding() {
  789. return this.uriEncoding;
  790. }
  791.  
  792. public void setUriEncoding(Charset uriEncoding) {
  793. this.uriEncoding = uriEncoding;
  794. }
  795.  
  796. public int getMaxConnections() {
  797. return this.maxConnections;
  798. }
  799.  
  800. public void setMaxConnections(int maxConnections) {
  801. this.maxConnections = maxConnections;
  802. }
  803.  
  804. public int getAcceptCount() {
  805. return this.acceptCount;
  806. }
  807.  
  808. public void setAcceptCount(int acceptCount) {
  809. this.acceptCount = acceptCount;
  810. }
  811.  
  812. public List<String> getAdditionalTldSkipPatterns() {
  813. return this.additionalTldSkipPatterns;
  814. }
  815.  
  816. public void setAdditionalTldSkipPatterns(List<String> additionalTldSkipPatterns) {
  817. this.additionalTldSkipPatterns = additionalTldSkipPatterns;
  818. }
  819.  
  820. void customizeTomcat(ServerProperties serverProperties,
  821. TomcatEmbeddedServletContainerFactory factory) {
  822. if (getBasedir() != null) {
  823. factory.setBaseDirectory(getBasedir());
  824. }
  825. factory.setBackgroundProcessorDelay(Tomcat.this.backgroundProcessorDelay);
  826. customizeRemoteIpValve(serverProperties, factory);
  827. if (this.maxThreads > 0) {
  828. customizeMaxThreads(factory);
  829. }
  830. if (this.minSpareThreads > 0) {
  831. customizeMinThreads(factory);
  832. }
  833. int maxHttpHeaderSize = (serverProperties.getMaxHttpHeaderSize() > 0
  834. ? serverProperties.getMaxHttpHeaderSize() : this.maxHttpHeaderSize);
  835. if (maxHttpHeaderSize > 0) {
  836. customizeMaxHttpHeaderSize(factory, maxHttpHeaderSize);
  837. }
  838. if (this.maxHttpPostSize != 0) {
  839. customizeMaxHttpPostSize(factory, this.maxHttpPostSize);
  840. }
  841. if (this.accesslog.enabled) {
  842. customizeAccessLog(factory);
  843. }
  844. if (getUriEncoding() != null) {
  845. factory.setUriEncoding(getUriEncoding());
  846. }
  847. if (serverProperties.getConnectionTimeout() != null) {
  848. customizeConnectionTimeout(factory,
  849. serverProperties.getConnectionTimeout());
  850. }
  851. if (this.redirectContextRoot != null) {
  852. customizeRedirectContextRoot(factory, this.redirectContextRoot);
  853. }
  854. if (this.maxConnections > 0) {
  855. customizeMaxConnections(factory);
  856. }
  857. if (this.acceptCount > 0) {
  858. customizeAcceptCount(factory);
  859. }
  860. if (!ObjectUtils.isEmpty(this.additionalTldSkipPatterns)) {
  861. factory.getTldSkipPatterns().addAll(this.additionalTldSkipPatterns);
  862. }
  863. if (serverProperties.getError()
  864. .getIncludeStacktrace() == ErrorProperties.IncludeStacktrace.NEVER) {
  865. customizeErrorReportValve(factory);
  866. }
  867. }
  868.  
  869. private void customizeErrorReportValve(
  870. TomcatEmbeddedServletContainerFactory factory) {
  871. factory.addContextCustomizers(new TomcatContextCustomizer() {
  872.  
  873. @Override
  874. public void customize(Context context) {
  875. ErrorReportValve valve = new ErrorReportValve();
  876. valve.setShowServerInfo(false);
  877. valve.setShowReport(false);
  878. context.getParent().getPipeline().addValve(valve);
  879. }
  880.  
  881. });
  882. }
  883.  
  884. private void customizeAcceptCount(TomcatEmbeddedServletContainerFactory factory) {
  885. factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
  886.  
  887. @Override
  888. @SuppressWarnings("deprecation")
  889. public void customize(Connector connector) {
  890. ProtocolHandler handler = connector.getProtocolHandler();
  891. if (handler instanceof AbstractProtocol) {
  892. AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
  893. protocol.setBacklog(Tomcat.this.acceptCount);
  894. }
  895. }
  896.  
  897. });
  898. }
  899.  
  900. private void customizeMaxConnections(
  901. TomcatEmbeddedServletContainerFactory factory) {
  902. factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
  903.  
  904. @Override
  905. public void customize(Connector connector) {
  906. ProtocolHandler handler = connector.getProtocolHandler();
  907. if (handler instanceof AbstractProtocol) {
  908. AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
  909. protocol.setMaxConnections(Tomcat.this.maxConnections);
  910. }
  911. }
  912.  
  913. });
  914. }
  915.  
  916. private void customizeConnectionTimeout(
  917. TomcatEmbeddedServletContainerFactory factory,
  918. final int connectionTimeout) {
  919. factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
  920.  
  921. @Override
  922. public void customize(Connector connector) {
  923. ProtocolHandler handler = connector.getProtocolHandler();
  924. if (handler instanceof AbstractProtocol) {
  925. AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
  926. protocol.setConnectionTimeout(connectionTimeout);
  927. }
  928. }
  929.  
  930. });
  931. }
  932.  
  933. private void customizeRemoteIpValve(ServerProperties properties,
  934. TomcatEmbeddedServletContainerFactory factory) {
  935. String protocolHeader = getProtocolHeader();
  936. String remoteIpHeader = getRemoteIpHeader();
  937. // For back compatibility the valve is also enabled if protocol-header is set
  938. if (StringUtils.hasText(protocolHeader) || StringUtils.hasText(remoteIpHeader)
  939. || properties.getOrDeduceUseForwardHeaders()) {
  940. RemoteIpValve valve = new RemoteIpValve();
  941. valve.setProtocolHeader(StringUtils.hasLength(protocolHeader)
  942. ? protocolHeader : "X-Forwarded-Proto");
  943. if (StringUtils.hasLength(remoteIpHeader)) {
  944. valve.setRemoteIpHeader(remoteIpHeader);
  945. }
  946. // The internal proxies default to a white list of "safe" internal IP
  947. // addresses
  948. valve.setInternalProxies(getInternalProxies());
  949. valve.setPortHeader(getPortHeader());
  950. valve.setProtocolHeaderHttpsValue(getProtocolHeaderHttpsValue());
  951. // ... so it's safe to add this valve by default.
  952. factory.addEngineValves(valve);
  953. }
  954. }
  955.  
  956. @SuppressWarnings("rawtypes")
  957. private void customizeMaxThreads(TomcatEmbeddedServletContainerFactory factory) {
  958. factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
  959. @Override
  960. public void customize(Connector connector) {
  961.  
  962. ProtocolHandler handler = connector.getProtocolHandler();
  963. if (handler instanceof AbstractProtocol) {
  964. AbstractProtocol protocol = (AbstractProtocol) handler;
  965. protocol.setMaxThreads(Tomcat.this.maxThreads);
  966. }
  967.  
  968. }
  969. });
  970. }
  971.  
  972. @SuppressWarnings("rawtypes")
  973. private void customizeMinThreads(TomcatEmbeddedServletContainerFactory factory) {
  974. factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
  975. @Override
  976. public void customize(Connector connector) {
  977.  
  978. ProtocolHandler handler = connector.getProtocolHandler();
  979. if (handler instanceof AbstractProtocol) {
  980. AbstractProtocol protocol = (AbstractProtocol) handler;
  981. protocol.setMinSpareThreads(Tomcat.this.minSpareThreads);
  982. }
  983.  
  984. }
  985. });
  986. }
  987.  
  988. @SuppressWarnings("rawtypes")
  989. private void customizeMaxHttpHeaderSize(
  990. TomcatEmbeddedServletContainerFactory factory,
  991. final int maxHttpHeaderSize) {
  992. factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
  993.  
  994. @Override
  995. public void customize(Connector connector) {
  996. ProtocolHandler handler = connector.getProtocolHandler();
  997. if (handler instanceof AbstractHttp11Protocol) {
  998. AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) handler;
  999. protocol.setMaxHttpHeaderSize(maxHttpHeaderSize);
  1000. }
  1001. }
  1002.  
  1003. });
  1004. }
  1005.  
  1006. private void customizeMaxHttpPostSize(
  1007. TomcatEmbeddedServletContainerFactory factory,
  1008. final int maxHttpPostSize) {
  1009. factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
  1010.  
  1011. @Override
  1012. public void customize(Connector connector) {
  1013. connector.setMaxPostSize(maxHttpPostSize);
  1014. }
  1015.  
  1016. });
  1017. }
  1018.  
  1019. private void customizeAccessLog(TomcatEmbeddedServletContainerFactory factory) {
  1020. AccessLogValve valve = new AccessLogValve();
  1021. valve.setPattern(this.accesslog.getPattern());
  1022. valve.setDirectory(this.accesslog.getDirectory());
  1023. valve.setPrefix(this.accesslog.getPrefix());
  1024. valve.setSuffix(this.accesslog.getSuffix());
  1025. valve.setRenameOnRotate(this.accesslog.isRenameOnRotate());
  1026. valve.setRequestAttributesEnabled(
  1027. this.accesslog.isRequestAttributesEnabled());
  1028. valve.setRotatable(this.accesslog.isRotate());
  1029. valve.setBuffered(this.accesslog.isBuffered());
  1030. valve.setFileDateFormat(this.accesslog.getFileDateFormat());
  1031. factory.addEngineValves(valve);
  1032. }
  1033.  
  1034. private void customizeRedirectContextRoot(
  1035. TomcatEmbeddedServletContainerFactory factory,
  1036. final boolean redirectContextRoot) {
  1037. factory.addContextCustomizers(new TomcatContextCustomizer() {
  1038.  
  1039. @Override
  1040. public void customize(Context context) {
  1041. context.setMapperContextRootRedirectEnabled(redirectContextRoot);
  1042. }
  1043.  
  1044. });
  1045. }
  1046.  
  1047. public static class Accesslog {
  1048.  
  1049. /**
  1050. * Enable access log.
  1051. */
  1052. private boolean enabled = false;
  1053.  
  1054. /**
  1055. * Format pattern for access logs.
  1056. */
  1057. private String pattern = "common";
  1058.  
  1059. /**
  1060. * Directory in which log files are created. Can be relative to the tomcat
  1061. * base dir or absolute.
  1062. */
  1063. private String directory = "logs";
  1064.  
  1065. /**
  1066. * Log file name prefix.
  1067. */
  1068. protected String prefix = "access_log";
  1069.  
  1070. /**
  1071. * Log file name suffix.
  1072. */
  1073. private String suffix = ".log";
  1074.  
  1075. /**
  1076. * Enable access log rotation.
  1077. */
  1078. private boolean rotate = true;
  1079.  
  1080. /**
  1081. * Defer inclusion of the date stamp in the file name until rotate time.
  1082. */
  1083. private boolean renameOnRotate;
  1084.  
  1085. /**
  1086. * Date format to place in log file name.
  1087. */
  1088. private String fileDateFormat = ".yyyy-MM-dd";
  1089.  
  1090. /**
  1091. * Set request attributes for IP address, Hostname, protocol and port used for
  1092. * the request.
  1093. */
  1094. private boolean requestAttributesEnabled;
  1095.  
  1096. /**
  1097. * Buffer output such that it is only flushed periodically.
  1098. */
  1099. private boolean buffered = true;
  1100.  
  1101. public boolean isEnabled() {
  1102. return this.enabled;
  1103. }
  1104.  
  1105. public void setEnabled(boolean enabled) {
  1106. this.enabled = enabled;
  1107. }
  1108.  
  1109. public String getPattern() {
  1110. return this.pattern;
  1111. }
  1112.  
  1113. public void setPattern(String pattern) {
  1114. this.pattern = pattern;
  1115. }
  1116.  
  1117. public String getDirectory() {
  1118. return this.directory;
  1119. }
  1120.  
  1121. public void setDirectory(String directory) {
  1122. this.directory = directory;
  1123. }
  1124.  
  1125. public String getPrefix() {
  1126. return this.prefix;
  1127. }
  1128.  
  1129. public void setPrefix(String prefix) {
  1130. this.prefix = prefix;
  1131. }
  1132.  
  1133. public String getSuffix() {
  1134. return this.suffix;
  1135. }
  1136.  
  1137. public void setSuffix(String suffix) {
  1138. this.suffix = suffix;
  1139. }
  1140.  
  1141. public boolean isRotate() {
  1142. return this.rotate;
  1143. }
  1144.  
  1145. public void setRotate(boolean rotate) {
  1146. this.rotate = rotate;
  1147. }
  1148.  
  1149. public boolean isRenameOnRotate() {
  1150. return this.renameOnRotate;
  1151. }
  1152.  
  1153. public void setRenameOnRotate(boolean renameOnRotate) {
  1154. this.renameOnRotate = renameOnRotate;
  1155. }
  1156.  
  1157. public String getFileDateFormat() {
  1158. return this.fileDateFormat;
  1159. }
  1160.  
  1161. public void setFileDateFormat(String fileDateFormat) {
  1162. this.fileDateFormat = fileDateFormat;
  1163. }
  1164.  
  1165. public boolean isRequestAttributesEnabled() {
  1166. return this.requestAttributesEnabled;
  1167. }
  1168.  
  1169. public void setRequestAttributesEnabled(boolean requestAttributesEnabled) {
  1170. this.requestAttributesEnabled = requestAttributesEnabled;
  1171. }
  1172.  
  1173. public boolean isBuffered() {
  1174. return this.buffered;
  1175. }
  1176.  
  1177. public void setBuffered(boolean buffered) {
  1178. this.buffered = buffered;
  1179. }
  1180.  
  1181. }
  1182.  
  1183. }
  1184.  
  1185. public static class Jetty {
  1186.  
  1187. /**
  1188. * Maximum size in bytes of the HTTP post or put content.
  1189. */
  1190. private int maxHttpPostSize = 0; // bytes
  1191.  
  1192. /**
  1193. * Number of acceptor threads to use.
  1194. */
  1195. private Integer acceptors;
  1196.  
  1197. /**
  1198. * Number of selector threads to use.
  1199. */
  1200. private Integer selectors;
  1201.  
  1202. public int getMaxHttpPostSize() {
  1203. return this.maxHttpPostSize;
  1204. }
  1205.  
  1206. public void setMaxHttpPostSize(int maxHttpPostSize) {
  1207. this.maxHttpPostSize = maxHttpPostSize;
  1208. }
  1209.  
  1210. public Integer getAcceptors() {
  1211. return this.acceptors;
  1212. }
  1213.  
  1214. public void setAcceptors(Integer acceptors) {
  1215. this.acceptors = acceptors;
  1216. }
  1217.  
  1218. public Integer getSelectors() {
  1219. return this.selectors;
  1220. }
  1221.  
  1222. public void setSelectors(Integer selectors) {
  1223. this.selectors = selectors;
  1224. }
  1225.  
  1226. void customizeJetty(final ServerProperties serverProperties,
  1227. JettyEmbeddedServletContainerFactory factory) {
  1228. factory.setUseForwardHeaders(serverProperties.getOrDeduceUseForwardHeaders());
  1229. if (this.acceptors != null) {
  1230. factory.setAcceptors(this.acceptors);
  1231. }
  1232. if (this.selectors != null) {
  1233. factory.setSelectors(this.selectors);
  1234. }
  1235. if (serverProperties.getMaxHttpHeaderSize() > 0) {
  1236. customizeMaxHttpHeaderSize(factory,
  1237. serverProperties.getMaxHttpHeaderSize());
  1238. }
  1239. if (this.maxHttpPostSize > 0) {
  1240. customizeMaxHttpPostSize(factory, this.maxHttpPostSize);
  1241. }
  1242.  
  1243. if (serverProperties.getConnectionTimeout() != null) {
  1244. customizeConnectionTimeout(factory,
  1245. serverProperties.getConnectionTimeout());
  1246. }
  1247. }
  1248.  
  1249. private void customizeConnectionTimeout(
  1250. JettyEmbeddedServletContainerFactory factory,
  1251. final int connectionTimeout) {
  1252. factory.addServerCustomizers(new JettyServerCustomizer() {
  1253.  
  1254. @Override
  1255. public void customize(Server server) {
  1256. for (org.eclipse.jetty.server.Connector connector : server
  1257. .getConnectors()) {
  1258. if (connector instanceof AbstractConnector) {
  1259. ((AbstractConnector) connector)
  1260. .setIdleTimeout(connectionTimeout);
  1261. }
  1262. }
  1263. }
  1264.  
  1265. });
  1266. }
  1267.  
  1268. private void customizeMaxHttpHeaderSize(
  1269. JettyEmbeddedServletContainerFactory factory,
  1270. final int maxHttpHeaderSize) {
  1271. factory.addServerCustomizers(new JettyServerCustomizer() {
  1272.  
  1273. @Override
  1274. public void customize(Server server) {
  1275. for (org.eclipse.jetty.server.Connector connector : server
  1276. .getConnectors()) {
  1277. try {
  1278. for (ConnectionFactory connectionFactory : connector
  1279. .getConnectionFactories()) {
  1280. if (connectionFactory instanceof HttpConfiguration.ConnectionFactory) {
  1281. customize(
  1282. (HttpConfiguration.ConnectionFactory) connectionFactory);
  1283. }
  1284. }
  1285. }
  1286. catch (NoSuchMethodError ex) {
  1287. customizeOnJetty8(connector, maxHttpHeaderSize);
  1288. }
  1289. }
  1290.  
  1291. }
  1292.  
  1293. private void customize(HttpConfiguration.ConnectionFactory factory) {
  1294. HttpConfiguration configuration = factory.getHttpConfiguration();
  1295. configuration.setRequestHeaderSize(maxHttpHeaderSize);
  1296. configuration.setResponseHeaderSize(maxHttpHeaderSize);
  1297. }
  1298.  
  1299. private void customizeOnJetty8(
  1300. org.eclipse.jetty.server.Connector connector,
  1301. int maxHttpHeaderSize) {
  1302. try {
  1303. connector.getClass().getMethod("setRequestHeaderSize", int.class)
  1304. .invoke(connector, maxHttpHeaderSize);
  1305. connector.getClass().getMethod("setResponseHeaderSize", int.class)
  1306. .invoke(connector, maxHttpHeaderSize);
  1307. }
  1308. catch (Exception ex) {
  1309. throw new RuntimeException(ex);
  1310. }
  1311. }
  1312.  
  1313. });
  1314. }
  1315.  
  1316. private void customizeMaxHttpPostSize(
  1317. JettyEmbeddedServletContainerFactory factory, final int maxHttpPostSize) {
  1318. factory.addServerCustomizers(new JettyServerCustomizer() {
  1319.  
  1320. @Override
  1321. public void customize(Server server) {
  1322. setHandlerMaxHttpPostSize(maxHttpPostSize, server.getHandlers());
  1323. }
  1324.  
  1325. private void setHandlerMaxHttpPostSize(int maxHttpPostSize,
  1326. Handler... handlers) {
  1327. for (Handler handler : handlers) {
  1328. if (handler instanceof ContextHandler) {
  1329. ((ContextHandler) handler)
  1330. .setMaxFormContentSize(maxHttpPostSize);
  1331. }
  1332. else if (handler instanceof HandlerWrapper) {
  1333. setHandlerMaxHttpPostSize(maxHttpPostSize,
  1334. ((HandlerWrapper) handler).getHandler());
  1335. }
  1336. else if (handler instanceof HandlerCollection) {
  1337. setHandlerMaxHttpPostSize(maxHttpPostSize,
  1338. ((HandlerCollection) handler).getHandlers());
  1339. }
  1340. }
  1341. }
  1342.  
  1343. });
  1344. }
  1345.  
  1346. }
  1347.  
  1348. public static class Undertow {
  1349.  
  1350. /**
  1351. * Maximum size in bytes of the HTTP post content.
  1352. */
  1353. private long maxHttpPostSize = 0; // bytes
  1354.  
  1355. /**
  1356. * Size of each buffer in bytes.
  1357. */
  1358. private Integer bufferSize;
  1359.  
  1360. /**
  1361. * Number of buffer per region.
  1362. */
  1363. @Deprecated
  1364. private Integer buffersPerRegion;
  1365.  
  1366. /**
  1367. * Number of I/O threads to create for the worker.
  1368. */
  1369. private Integer ioThreads;
  1370.  
  1371. /**
  1372. * Number of worker threads.
  1373. */
  1374. private Integer workerThreads;
  1375.  
  1376. /**
  1377. * Allocate buffers outside the Java heap.
  1378. */
  1379. private Boolean directBuffers;
  1380.  
  1381. private final Accesslog accesslog = new Accesslog();
  1382.  
  1383. public long getMaxHttpPostSize() {
  1384. return this.maxHttpPostSize;
  1385. }
  1386.  
  1387. public void setMaxHttpPostSize(long maxHttpPostSize) {
  1388. this.maxHttpPostSize = maxHttpPostSize;
  1389. }
  1390.  
  1391. public Integer getBufferSize() {
  1392. return this.bufferSize;
  1393. }
  1394.  
  1395. public void setBufferSize(Integer bufferSize) {
  1396. this.bufferSize = bufferSize;
  1397. }
  1398.  
  1399. @DeprecatedConfigurationProperty(reason = "The property is not used by Undertow. See https://issues.jboss.org/browse/UNDERTOW-587 for details")
  1400. public Integer getBuffersPerRegion() {
  1401. return this.buffersPerRegion;
  1402. }
  1403.  
  1404. public void setBuffersPerRegion(Integer buffersPerRegion) {
  1405. this.buffersPerRegion = buffersPerRegion;
  1406. }
  1407.  
  1408. public Integer getIoThreads() {
  1409. return this.ioThreads;
  1410. }
  1411.  
  1412. public void setIoThreads(Integer ioThreads) {
  1413. this.ioThreads = ioThreads;
  1414. }
  1415.  
  1416. public Integer getWorkerThreads() {
  1417. return this.workerThreads;
  1418. }
  1419.  
  1420. public void setWorkerThreads(Integer workerThreads) {
  1421. this.workerThreads = workerThreads;
  1422. }
  1423.  
  1424. public Boolean getDirectBuffers() {
  1425. return this.directBuffers;
  1426. }
  1427.  
  1428. public void setDirectBuffers(Boolean directBuffers) {
  1429. this.directBuffers = directBuffers;
  1430. }
  1431.  
  1432. public Accesslog getAccesslog() {
  1433. return this.accesslog;
  1434. }
  1435.  
  1436. void customizeUndertow(final ServerProperties serverProperties,
  1437. UndertowEmbeddedServletContainerFactory factory) {
  1438. if (this.bufferSize != null) {
  1439. factory.setBufferSize(this.bufferSize);
  1440. }
  1441. if (this.ioThreads != null) {
  1442. factory.setIoThreads(this.ioThreads);
  1443. }
  1444. if (this.workerThreads != null) {
  1445. factory.setWorkerThreads(this.workerThreads);
  1446. }
  1447. if (this.directBuffers != null) {
  1448. factory.setDirectBuffers(this.directBuffers);
  1449. }
  1450. if (this.accesslog.enabled != null) {
  1451. factory.setAccessLogEnabled(this.accesslog.enabled);
  1452. }
  1453. factory.setAccessLogDirectory(this.accesslog.dir);
  1454. factory.setAccessLogPattern(this.accesslog.pattern);
  1455. factory.setAccessLogPrefix(this.accesslog.prefix);
  1456. factory.setAccessLogSuffix(this.accesslog.suffix);
  1457. factory.setAccessLogRotate(this.accesslog.rotate);
  1458. factory.setUseForwardHeaders(serverProperties.getOrDeduceUseForwardHeaders());
  1459. if (serverProperties.getMaxHttpHeaderSize() > 0) {
  1460. customizeMaxHttpHeaderSize(factory,
  1461. serverProperties.getMaxHttpHeaderSize());
  1462. }
  1463. if (this.maxHttpPostSize > 0) {
  1464. customizeMaxHttpPostSize(factory, this.maxHttpPostSize);
  1465. }
  1466.  
  1467. if (serverProperties.getConnectionTimeout() != null) {
  1468. customizeConnectionTimeout(factory,
  1469. serverProperties.getConnectionTimeout());
  1470. }
  1471. }
  1472.  
  1473. private void customizeConnectionTimeout(
  1474. UndertowEmbeddedServletContainerFactory factory,
  1475. final int connectionTimeout) {
  1476. factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
  1477. @Override
  1478. public void customize(Builder builder) {
  1479. builder.setSocketOption(UndertowOptions.NO_REQUEST_TIMEOUT,
  1480. connectionTimeout);
  1481. }
  1482. });
  1483. }
  1484.  
  1485. private void customizeMaxHttpHeaderSize(
  1486. UndertowEmbeddedServletContainerFactory factory,
  1487. final int maxHttpHeaderSize) {
  1488. factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
  1489.  
  1490. @Override
  1491. public void customize(Builder builder) {
  1492. builder.setServerOption(UndertowOptions.MAX_HEADER_SIZE,
  1493. maxHttpHeaderSize);
  1494. }
  1495.  
  1496. });
  1497. }
  1498.  
  1499. private void customizeMaxHttpPostSize(
  1500. UndertowEmbeddedServletContainerFactory factory,
  1501. final long maxHttpPostSize) {
  1502. factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
  1503.  
  1504. @Override
  1505. public void customize(Builder builder) {
  1506. builder.setServerOption(UndertowOptions.MAX_ENTITY_SIZE,
  1507. maxHttpPostSize);
  1508. }
  1509.  
  1510. });
  1511. }
  1512.  
  1513. public static class Accesslog {
  1514.  
  1515. /**
  1516. * Enable access log.
  1517. */
  1518. private Boolean enabled;
  1519.  
  1520. /**
  1521. * Format pattern for access logs.
  1522. */
  1523. private String pattern = "common";
  1524.  
  1525. /**
  1526. * Log file name prefix.
  1527. */
  1528. protected String prefix = "access_log.";
  1529.  
  1530. /**
  1531. * Log file name suffix.
  1532. */
  1533. private String suffix = "log";
  1534.  
  1535. /**
  1536. * Undertow access log directory.
  1537. */
  1538. private File dir = new File("logs");
  1539.  
  1540. /**
  1541. * Enable access log rotation.
  1542. */
  1543. private boolean rotate = true;
  1544.  
  1545. public Boolean getEnabled() {
  1546. return this.enabled;
  1547. }
  1548.  
  1549. public void setEnabled(Boolean enabled) {
  1550. this.enabled = enabled;
  1551. }
  1552.  
  1553. public String getPattern() {
  1554. return this.pattern;
  1555. }
  1556.  
  1557. public void setPattern(String pattern) {
  1558. this.pattern = pattern;
  1559. }
  1560.  
  1561. public String getPrefix() {
  1562. return this.prefix;
  1563. }
  1564.  
  1565. public void setPrefix(String prefix) {
  1566. this.prefix = prefix;
  1567. }
  1568.  
  1569. public String getSuffix() {
  1570. return this.suffix;
  1571. }
  1572.  
  1573. public void setSuffix(String suffix) {
  1574. this.suffix = suffix;
  1575. }
  1576.  
  1577. public File getDir() {
  1578. return this.dir;
  1579. }
  1580.  
  1581. public void setDir(File dir) {
  1582. this.dir = dir;
  1583. }
  1584.  
  1585. public boolean isRotate() {
  1586. return this.rotate;
  1587. }
  1588.  
  1589. public void setRotate(boolean rotate) {
  1590. this.rotate = rotate;
  1591. }
  1592.  
  1593. }
  1594.  
  1595. }
  1596.  
  1597. /**
  1598. * {@link ServletContextInitializer} to apply appropriate parts of the {@link Session}
  1599. * configuration.
  1600. */
  1601. private static class SessionConfiguringInitializer
  1602. implements ServletContextInitializer {
  1603.  
  1604. private final Session session;
  1605.  
  1606. SessionConfiguringInitializer(Session session) {
  1607. this.session = session;
  1608. }
  1609.  
  1610. @Override
  1611. public void onStartup(ServletContext servletContext) throws ServletException {
  1612. if (this.session.getTrackingModes() != null) {
  1613. servletContext.setSessionTrackingModes(this.session.getTrackingModes());
  1614. }
  1615. configureSessionCookie(servletContext.getSessionCookieConfig());
  1616. }
  1617.  
  1618. private void configureSessionCookie(SessionCookieConfig config) {
  1619. Cookie cookie = this.session.getCookie();
  1620. if (cookie.getName() != null) {
  1621. config.setName(cookie.getName());
  1622. }
  1623. if (cookie.getDomain() != null) {
  1624. config.setDomain(cookie.getDomain());
  1625. }
  1626. if (cookie.getPath() != null) {
  1627. config.setPath(cookie.getPath());
  1628. }
  1629. if (cookie.getComment() != null) {
  1630. config.setComment(cookie.getComment());
  1631. }
  1632. if (cookie.getHttpOnly() != null) {
  1633. config.setHttpOnly(cookie.getHttpOnly());
  1634. }
  1635. if (cookie.getSecure() != null) {
  1636. config.setSecure(cookie.getSecure());
  1637. }
  1638. if (cookie.getMaxAge() != null) {
  1639. config.setMaxAge(cookie.getMaxAge());
  1640. }
  1641. }
  1642.  
  1643. }
  1644.  
  1645. }
在这个类里我们可以找到customizeTomcat方法,大家自行看看喽,类图如下:


  

Spring中的BeanPostProcessor的更多相关文章

  1. Spring中的BeanPostProcessor详解

    Spring中的BeanPostProcessor详解 概述 BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初 ...

  2. 谈谈Spring中的BeanPostProcessor接口

    一.前言   这几天正在复习Spring的相关内容,在了解bean的生命周期的时候,发现其中涉及到一个特殊的接口--BeanPostProcessor接口.由于网上没有找到比较好的博客,所有最后花了好 ...

  3. Spring中的BeanPostProcessor和BeanFactoryPostProcessor

    BeanPostProcessor BeanFactoryPostProcessor 标准ioc容器初始化之后的后置处理器 BeanDefintionRegisterPostProcessor 在所有 ...

  4. Spring中BeanPostProcessor

    Spring中BeanPostProcessor 前言: 本文旨在介绍Spring动态配置数据源的方式,即对一个DataSource的配置诸如jdbcUrl,user,password,driverC ...

  5. spring(三):spring中BeanPostProcessor的使用

    spring中实现BeanPostProcessor的后置处理器 ApplicationContextAwareProcessor 进入该实现类内部 可以看到:该类帮我们组建IOC容器,判断我们的be ...

  6. Spring点滴五:Spring中的后置处理器BeanPostProcessor讲解

    BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcesso ...

  7. 通过BeanPostProcessor理解Spring中Bean的生命周期

    通过BeanPostProcessor理解Spring中Bean的生命周期及AOP原理 Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProces ...

  8. Spring点滴十一:Spring中BeanFactoryPostProcessor和BeanPostProcessor区别

    Spring中BeanFactoryPostProcessor和BeanPostProcessor都是Spring初始化bean时对外暴露的扩展点.两个接口从名字看起来很相似,但是作用及使用场景却不同 ...

  9. Spring中的后置处理器BeanPostProcessor讲解

    Spring中提供了很多PostProcessor供开发者进行拓展,例如:BeanPostProcessor.BeanFactoryPostProcessor.BeanValidationPostPr ...

随机推荐

  1. LA 3708 && POJ 3154 Graveyard (思维)

    题意:在周长为10000的圆上等距分布着n个雕塑,现在又加入m个,现在让m+n个等距分布,那就得移动一些原有的雕塑,问你移动的最少总距离是多少. 析:首先我们可以知道,至少有一个雕塑是可以不用移动的, ...

  2. 1) Apache Maven 's README.txt

    Apache Maven What is it? ----------- Maven is a software project management and comprehension tool. ...

  3. HDU 3455 Leap Frog 2016-09-12 16:34 43人阅读 评论(0) 收藏

    Leap Frog Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  4. android Qzone的App热补丁热修复技术

    转自:https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731 ...

  5. .Net socket服务器编程之为何也高效

    说到Socket编程,肯定大部分人举手c,c++.可惜现在已没有机会去追随并达到写服务器的水平,所以将就下还是考虑c#版的Socket服务器吧. 经过一番查询,试用.一些数据和事实还是浮出水面,同时对 ...

  6. delphi 动态加载dll

    引入文件 DLL比较复杂时,可以为它的声明专门创建一个引入单元,这会使该DLL变得更加容易维护和查看.引入单元的格式如下: unit MyDllImport; {Import unit for MyD ...

  7. SpringBoot tomcat

    该文的前提是已经可以在控制台运行成功,有些时候想放在tomcat里运行 大致分为如下几步 1.配置文件更改 <dependency> <groupId>org.springfr ...

  8. PLSQL(PL/SQL)集成Team Foundation Server (TFS),实现数据库代码的版本管理

    PL/SQL是面向Oralcle数据库的集成开发环境,是众多Oracle数据库开发人员的主要工具.由于PL/SQL(百度百科)不仅是一种SQL语言,更是一种过程编程语言,在项目实施过程中,会积累大量除 ...

  9. linux系统编程之进程(一):进程与程序

    本节目标: 什么是程序 什么是进程 进程数据结构 进程与程序区别与联系 一,什么是程序? 程序是完成特定任务的一系列指令集合 二,什么是进程? 从用户的角度来看进程是程序的一次动态执行过程 从操作系统 ...

  10. C# 使用ftp下载一个文件夹下的所有文件,包括子目录文件夹

    这篇博客给大家补充一个方法,就是得到一个目录下的所有文件名称.在前端调用,大家写一个递归去遍历就可以了,我在这里就不在写了.具体ftp下载的方法在我的另一篇博客里有,需要的可以去看一下. /// &l ...