总结:
1)SpringBoot先加载所有自动配置类
2)每个自动配置类按照条件@Conditional参数进行生效,绑定配置文件指定的值
一般都是XXx.properties来,x.properties和配置文件绑定
3)生效的配置就会给容器中装配@Bean标记的组件,当然符合组件@Conditional要求
4)只要有这些组件,相当于这些功能就有了
5)定制配置
a)只要有用户自己配置的@Bean,以用户优先
b)修改配置文件:用户去看这个类对应的配置文件
导入的lib里面的jar中: XXAutoConfigration到导入了很多组件,组件又从xxxProperties中取值,
xxxProperties又从配置文件中取值
上文说到会默认全部加载127个jar包,但是会根据每个jar里面的@Conditional去按需配置
断点:
@SpringBootApplication--》@EnableAutoConfiguration-->AutoConfigurationImportSelector->
这127个是
this = {AutoConfigurationImportSelector@3479}
annotationMetadata = {StandardAnnotationMetadata@3480}
mergedAnnotations = {TypeMappedAnnotations@3794}
nestedAnnotationsAsMap = true
annotationTypes = {Collections$UnmodifiableSet@3795} size = 1
introspectedClass = {Class@1363} "class com.i7i8i9.boot.MainApplication"
attributes = {AnnotationAttributes@3798} size = 2
configurations = {LinkedList@3802} size = 127
0 = "org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration"
1 = "org.springframework.boot.autoconfigure.aop.AopAutoConfiguration"
2 = "org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration"
3 = "org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration"
4 = "org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration"
5 = "org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration"
6 = "org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration"
7 = "org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration"
8 = "org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration"
9 = "org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration"
10 = "org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration"
11 = "org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration"
12 = "org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration"
13 = "org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration"
14 = "org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration"
15 = "org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration"
16 = "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration"
17 = "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration"
18 = "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration"
19 = "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration"
20 = "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration"
21 = "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration"
22 = "org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration"
23 = "org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration"
24 = "org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration"
25 = "org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration"
26 = "org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration"
27 = "org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration"
28 = "org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration"
29 = "org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration"
30 = "org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration"
31 = "org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration"
32 = "org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration"
33 = "org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration"
34 = "org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration"
35 = "org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration"
36 = "org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration"
37 = "org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration"
38 = "org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration"
39 = "org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration"
40 = "org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration"
41 = "org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration"
42 = "org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration"
43 = "org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration"
44 = "org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration"
45 = "org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration"
46 = "org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration"
47 = "org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration"
48 = "org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration"
49 = "org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration"
50 = "org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration"
51 = "org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration"
52 = "org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration"
53 = "org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration"
54 = "org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration"
55 = "org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration"
56 = "org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration"
57 = "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration"
58 = "org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration"
59 = "org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration"
60 = "org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration"
61 = "org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration"
62 = "org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration"
63 = "org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration"
64 = "org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration"
65 = "org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration"
66 = "org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration"
67 = "org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration"
68 = "org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration"
69 = "org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration"
70 = "org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration"
71 = "org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration"
72 = "org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration"
73 = "org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration"
74 = "org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration"
75 = "org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration"
76 = "org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration"
77 = "org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration"
78 = "org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration"
79 = "org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration"
80 = "org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration"
81 = "org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration"
82 = "org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration"
83 = "org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration"
84 = "org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration"
85 = "org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration"
86 = "org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration"
87 = "org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration"
88 = "org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration"
89 = "org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration"
90 = "org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration"
91 = "org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration"
92 = "org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration"
93 = "org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration"
94 = "org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration"
95 = "org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration"
96 = "org.springframework.boot.autoconfigure.session.SessionAutoConfiguration"
97 = "org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration"
98 = "org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration"
99 = "org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration"
在其中可以发现 aop configuration确实导入进来了
根据
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"auto"},
havingValue = "true",
matchIfMissing = true
)
需要配置文件中有 spring.aop的才生效,最后一句matchIfMissing = true代表没配也认为你配了
接下来看
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({Advice.class})
static class AspectJAutoProxyingConfiguration {
AspectJAutoProxyingConfiguration() {
}
基于是否存在
这个advice 从import org.aspectj.weaver.Advice来看应该是aspectj下
在当前类中没有找到
再看这里面的另外一个类
ConditionalOnMissingClass({"org.aspectj.weaver.Advice"})没有advice时使用
@ConditionalOnMissingClass({"org.aspectj.weaver.Advice"})
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "true",
matchIfMissing = true
)
static class ClassProxyingConfiguration {
ClassProxyingConfiguration(BeanFactory beanFactory) {
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
当前类中可以查到
AutoConfiguration都是自动配置类,但是不一定生效
可以看到其也是springboot一启动就加载
另外看是否按需加载
@ConditionalOnClass({CacheManager.class})
在idea中搜索其存在于spring核心包
第二个判断:是判断有没有CacheAspectSupport这种类型的Bean
@ConditionalOnBean({CacheAspectSupport.class})
在MainApplication中加入
String[] beanNamesforCache= applicationContext.getBeanNamesForType(CacheAspectSupport.class);
System.out.println("beanNamesforCache数量==="+beanNamesforCache.length);
输出:
beanNamesforCache数量===0
代表没有生效
那么其下的@Bean给容器加东西的这种自然也不会生效
@Bean
@ConditionalOnMissingBean
public CacheManagerCustomizers cacheManagerCustomizers(ObjectProvider> customizers) {
return new CacheManagerCustomizers((List)customizers.orderedStream().collect(Collectors.toList()));
}
@Bean
public CacheManagerValidator cacheAutoConfigurationValidator(CacheProperties cacheProperties, ObjectProvider cacheManager) {
return new CacheManagerValidator(cacheProperties, cacheManager);
}
@Configuration( //说明是一个配置类
proxyBeanMethods = false
)
@ConditionalOnWebApplication( //需要是原生web,springboot2支持响应式和原生两种
type = Type.SERVLET
)
@ConditionalOnClass({DispatcherServlet.class})
第二个条件
@ConditionalOnWebApplication( //需要是原生web,springboot2支持响应式和原生两种
type = Type.SERVLET
)
现在我们用的spring-boot就是原生的SpringMVC
响应式导入的是SpringWebFlux
第三个条件
在class中存在以下类
@Configuration(
proxyBeanMethods = false
)
@Conditional({DispatcherServletRegistrationCondition.class})
@ConditionalOnClass({ServletRegistration.class})
@EnableConfigurationProperties({WebMvcProperties.class})
@Import({DispatcherServletConfiguration.class})
protected static class DispatcherServletRegistrationConfiguration {
确定有
接下来是熟悉的跟配置文件绑定的功能
@EnableConfigurationProperties({WebMvcProperties.class})
进入可以看到其绑定了 spring.mvc,也就是说配置文件中spring mvc开头的都会被读取
另外检查一下容器中是否有WebMvcProperties对象
String[] beanWebMVC= applicationContext.getBeanNamesForType(WebMvcProperties.class); System.out.println("beanWebMVC数量==="+beanWebMVC.length);
则判断该子类对象生效了
查看子类中方法,@Bean表示加入到容器中,另外发现new了Servlet说明底层帮我们创建了SpringMVC核心对象 DispatcherServlet
@Bean(
name = {"dispatcherServlet"}
)
public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
return dispatcherServlet;
}
另外一个Bean是文件上传解析器
@Bean
@ConditionalOnBean({MultipartResolver.class}) //容器中有这个类型组件
@ConditionalOnMissingBean(
name = {"multipartResolver"} //容器中没有这个名字的组件,SpringMVC要求必须是这个名字
)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
return resolver;
}
}
有趣的是这个用法
public MultipartResolver multipartResolver(MultipartResolver resolver) {
return resolver;
}
利用了给@Bean方法传递了参数,这个参数的值会自动去容器中找
解决了名字没有按照springmvc要求命名为multipartResolver的问题
防止有些用户配置的文件上传解析器不符合规范
这样读进来后,返回,因为方法名字是规范的multipartResolve,符合SpringMVC要求
先写一个中文例子
controller:
@RequestMapping("/hello")
public String handle01(@RequestParam("name") String name){
return "Hello,你好,i7i8i9"+name;
}
在浏览器中请求
为什么不乱吗,原因在于
@Configuration( //声明是一个配置类
proxyBeanMethods = false
)
@EnableConfigurationProperties({ServerProperties.class}) //会去读配置文件
@ConditionalOnWebApplication(
type = Type.SERVLET //是不是原生,是的,我们用的是PSringMVC,不是响应式,没有webflux
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
prefix = "server.servlet.encoding", //配置文件中是否有这个前缀
value = {"enabled"}, //前缀的值是 enables
matchIfMissing = true //没配也生效的意思
)
public class HttpEncodingAutoConfiguration {
private final Encoding properties;
public HttpEncodingAutoConfiguration(ServerProperties properties) {
this.properties = properties.getServlet().getEncoding();
}
确实有
进入子类
characterEncodingFilter()是SpringMVC解决编码问题的,用这个拦截,否则就会乱码
@ConditionalOnMissingBean 容器中没有配这个就会帮你配
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));
return filter;
}
spring设计模式:会自动配置组件,但是优先使用用户的
用户如果想自己写,可以写在 Myconfig这个配置类中,比如
@Bean
public CharacterEncodingFilter characterEncodingFilter() {return null}
另外可以根据类Property去修改配置文件,比如
在配置文件中可以根据这个前缀要求去修改:
要修改
ServerProperties.class,进入
详细一点,就是
@ConditionalOnProperty( prefix = "server.servlet.encoding",