设为首页 收藏本站
查看: 2283|回复: 0

[经验分享] Spring Boot自动配置类

[复制链接]

尚未签到

发表于 2017-3-3 09:05:41 | 显示全部楼层 |阅读模式
http://docs.spring.io/spring-boot/docs/current/api/overview-summary.html

http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#auto-configuration-classes



前提

1、一般来说,xxxAware接口,都提供了一个setXxx的方法,以便于其实现类将Xxx注入自身的xxx字段中,从而进行操作。

例如 ApplicationContextAware ,就提供了 void setApplicationContext(ApplicationContext applicationContext)throwsBeansException; ,从而让其实现可以直接操作 applicationContext 。

2、Spring中的 BeanFactory,这是访问bean container 的root interface。其实现类的对象通常拥有一系列 bean 定义,并以不同的String 名字来区分。

但是,官方文档不建议直接使用这种方式获取bean,而是建议使用注入的方式获取bean(@Autowire)。--这个,前期不能使用初始化注入吧?

  正文
  Spring Boot提供的自动配置都是位于包 org.springframework.boot.autoconfigure 之下。


注意,

       ① 这里是Spring Boot提供的,而非第三方(如MyBatis-Spring-Boot-Starter)提供的。

       ② 不包含Spring Boot Actuator部分的。



Spring Boot的自动配置类可以通过autoconfig report查看,需要开启 --debug 或 -Debug。或者在 Actuator 项目的autoconfig 端点查看。



这里先从Web开始学习


由于Spring Boot的web Starter集成了Spring MVC,而非其他,所以实际上提供的Web自动配置为Spring MVC的自动配置。

Spring MVC的自动配置在包 org.springframework.boot.autoconfigure.web 之下,该包中的内容如下:

DSC0000.png

从上图中可以清楚的看到Spring Boot为Spring MVC提供了哪些自动配置:



  • DispatcherServletAutoConfiguration.class
  • EmbeddedServletContainerAutoConfiguration.class
  • ErrorMvcAutoConfiguration.class
  • GsonHttpMessageConvertersConfiguration.class
  • HttpEncodingAutoConfiguration.class
  • HttpMessageConvertersAutoConfiguration.class
  • JacksonHttpMessageConvertersConfiguration.class
  • MultipartAutoConfiguration.class
  • ServerPropertiesAutoConfiguration.class
  • WebClientAutoConfiguration.class
  • WebMvcAutoConfiguration.class




另外,还有一类文件:xxxProperties.class。这些文件都是 @ConfigurationProperties classes 。

@Configuration classes上可以使用 @EnableConfigurationProperties 进行 @ConfigurationProperties classes 的注入。 -- 也可以在@Configuration classes内部使用@Bean,略麻烦。



接下来,我们有针对性的来捋一遍。



先看一下这些类的声明



DSC0001.gif DSC0002.gif


1 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
2 @Configuration
3 @ConditionalOnWebApplication
4 @ConditionalOnClass(DispatcherServlet.class)
5 @AutoConfigureAfter(EmbeddedServletContainerAutoConfiguration.class)
6 public class DispatcherServletAutoConfiguration { ... }
7
8 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
9 @Configuration
10 @ConditionalOnWebApplication
11 @Import(BeanPostProcessorsRegistrar.class)
12 public class EmbeddedServletContainerAutoConfiguration { ... }
13
14 @Configuration
15 @ConditionalOnClass(Gson.class)
16 class GsonHttpMessageConvertersConfiguration { ... }
17
18 @Configuration
19 @EnableConfigurationProperties(HttpEncodingProperties.class)
20 @ConditionalOnWebApplication
21 @ConditionalOnClass(CharacterEncodingFilter.class)
22 @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
23 public class HttpEncodingAutoConfiguration { ... }
24
25 @Configuration
26 @ConditionalOnClass(HttpMessageConverter.class)
27 @AutoConfigureAfter({ GsonAutoConfiguration.class, JacksonAutoConfiguration.class })
28 @Import({ JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class })
29 public class HttpMessageConvertersAutoConfiguration { ... }
30
31 @Configuration
32 class JacksonHttpMessageConvertersConfiguration{ ... }
33
34 @Configuration
35 @ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class })
36 @ConditionalOnProperty(prefix = "spring.http.multipart", name = "enabled", matchIfMissing = true)
37 @EnableConfigurationProperties(MultipartProperties.class)
38 public class MultipartAutoConfiguration { ... }
39
40 @Configuration
41 @EnableConfigurationProperties
42 @ConditionalOnWebApplication
43 public class ServerPropertiesAutoConfiguration { ... }
44
45 @Configuration
46 @AutoConfigureAfter(HttpMessageConvertersAutoConfiguration.class)
47 public class WebClientAutoConfiguration { ... }
48
49 @Configuration
50 @ConditionalOnWebApplication
51 @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurerAdapter.class })
52 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
53 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
54 @AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
55 public class WebMvcAutoConfiguration { ... }
View Code

整理一下优先级:

最高级

        EmbeddedServletContainerAutoConfiguration


        DispatcherServletAutoConfiguration

次高级

        WebMvcAutoConfiguration



无级别

        HttpEncodingAutoConfiguration

        MultipartAutoConfiguration


        ServerPropertiesAutoConfiguration



  依赖链(属于无级别)

        GsonHttpMessageConvertersConfiguration


        JacksonHttpMessageConvertersConfiguration

        HttpMessageConvertersAutoConfiguration

        WebClientAutoConfiguration



一、先看一下 EmbeddedServletContainerAutoConfiguration,这是内置Servlet容器的自动配置 -- 默认就是那个 pivotal-tc-server (定制版tomcat,商业的)。

该类的声明如下:




1 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) // 自动配置里面的最高优先级
2 @Configuration
3 @ConditionalOnWebApplication // 仅限于web应用
4 @Import(BeanPostProcessorsRegistrar.class) // 导入内置容器的设置
5 public class EmbeddedServletContainerAutoConfiguration {
6     @Configuration
7     @ConditionalOnClass({ Servlet.class, Tomcat.class })
8     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
9     public static class EmbeddedTomcat {
10         // ...
11     }
12
13     @Configuration
14     @ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class })
15     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
16     public static class EmbeddedJetty {
17         // ...
18     }
19
20     @Configuration
21     @ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
22     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
23     public static class EmbeddedUndertow {
24         // ...
25     }
26
27     public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
28         // ...
29     }
30 }







@ConditionalOnWebApplication 是基于application context 是否 web application context 进行判断。

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) ,这里的 Ordered.HIGHEST_PRECEDENCE  其实是int类型的最小值,代表最高的优先级。

@Import(BeanPostProcessorsRegistrar.class) ,这里 BeanPostProcessorsRegistrar 中进行的操作是注册了一个bean,  EmbeddedServletContainerCustomizerBeanPostProcessor 。是通过 ImportBeanDefinitionRegistrar  进行早期注册。





这个配置类,内部共有4个静态内部类:3个容器类(tomcat、jetty、undertow)、1个bean注册类。




  • 3个容器类是基于classpath中的class文件来判断使用哪个容器,默认使用内置容器。
  • 1个bean注册类则是注册了一个 BeanPostProcessor bean,用于对容器进行定制。




下面重点看一下这个bean注册类的相关。

1、EmbeddedServletContainerCustomizerBeanPostProcessor






public class EmbeddedServletContainerCustomizerBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
// ...
}
  2、BeanPostProcessor接口,该接口内容如下:









1 public interface BeanPostProcessor {
2     Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
3     Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
4 }
View Code  根据方法的名字可以知道这是对在bean初始化之前、之后进行操作的方法。


该接口的Javadoc如下:




  • BeanPostProcessor则是一个工厂钩子(factory hook),用于对新beans实例进行定制修改,例如检查它们的标记接口或者使用代理包装它们。
  • ApplicationContexts能够自动探测BeanPostProcessor beans,并将他们应用到后续创建的任意beans中。
  • 简单bean工厂允许代码化的注册post-processors,并将注册的post-processors应用到该工厂创建的所有bean中。
  • 典型的做法是,通过标记接口装配beans时,post-processors会实现postProcessBeforeInitialization;而使用代理包装beans时则会实现postProcessAfterInitialization


EmbeddedServletContainerCustomizerBeanPostProcessor 中提供了 postProcessBeforeInitialization 的实现(对bean有更多的操作,而非直接返回bean),对内置容器进行了定制操作。(插一句,这里的定制操作是通过applicationContext 中 EmbeddedServletContainerCustomizer beans进行的,所以需要先获取applicationContext(ApplicationContextAware的功劳),再从applicationContext中获取EmbeddedServletContainerCustomizer beans)

3、回过头来再看一下BeanPostProcessorsRegistrar








1 public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
2     // ...
3 }
View Code  这是个静态内部类,实现了两个接口。




4、接口ImportBeanDefinitionRegistrar






public interface ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
  该接口用于在系统处理@Configuration class时注册更多的bean。是bean定义级别的操作,而非@Bean method/instance级别的。


这个方法,应该是在Spring加载bean时被Spring调用。

org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader  未完待续。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-349487-1-1.html 上篇帖子: Kibana4简单使用 下篇帖子: apache phoenix4.6配置tracing
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表