上一章Springboot核心技术(一):
http://blog.csdn.net/qq_22860341/article/details/79173580
上一章节主要讲解Spring核心功能,banner的设置,外部配置文件,日志等文件。本章接着上章继续完善。
转载请注明出处。
上一章我们见识了SpringBoot为我们做的自动配置,本节在了解SpringBoot运行原理后,用我们已经掌握的知识自定义一个starter pom.
SpringBoot关于自动配置的源码在下面jar中:
想知道SpringBoot提供了哪些自动配置。查看这里的源码即可。
可以通过下列方式查看项目中启用和未启用的自动配置:
(1)运行jar时增加–debug参数
java -jar xxx.jar --debug
(2)在application.properties中增加
debug=true
(3)在STS中设置,eclipse中,
在控制台
已启用自动配置:
1.运行原理
关于SpringBoot运行原理,我们还是回归@SpringBootApplication注解上,这个注解是一个组合注解。
@SpringBootApplication源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
@AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
Class>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
@AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
String[] excludeName() default {};
/**
* Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
* for a type-safe alternative to String-based package names.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
/**
* Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
* scan for annotated components. The package of each class specified will be scanned.
*
* Consider creating a special no-op marker class or interface in each package that
* serves no purpose other than being referenced by this attribute.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class>[] scanBasePackageClasses() default {};
}
它的核心功能主要由@EnableAutoConfiguration注解提供的,我们一起看下@EnableAutoConfiguration注解的源码。
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
这里关键在于@Import(EnableAutoConfigurationImportSelector.class)
我们的spring-boot-autoconfigure.1.5.9.x.jar里面META-INF有一个spring.factories文件此文件中声明了哪些自动配置:
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnClassCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer
# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider
核心注解
打开上面任意一个AutoConfiguration文件,一般都有下面的条件注解,在spring-boot-autoconfigure-1.5.9.x.jar的org.springframwork.boot.autoconfigure.condition包下:
@ConditionalOnBean 当容器里有指定的Bean的条件下。
@ConditionalOnClass 当类路径下有指定的类的条件下
@ConditionalOnExpression 基于SpEL表达式作为条件判断
@ConditionalOnJava 基于JVM版本作为判断条件
@ConditionalOnJndi 在JNDI存在的条件下查找指定位置
@ConditionalOn。。。。。。。。。。。
@ConditionalOn。。。。。。。。。。,
@ConditionalOnWebApplication 当前项目是Web项目的条件下。
这些注解都是组合了@Conditional元注解,只是使用了不同的条件(Condition).
下面我们分析一下@ConditionalOnWebApplication注解
源码附上:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional;
/**
* {@link Conditional} that only matches when the application context is a web application
* context.
*
* @author Dave Syer
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnWebApplicationCondition.class)
public @interface ConditionalOnWebApplication {
}
从源码可以看出,次注解使用的是OnWebApplicationCondition,下面我们看看它的构成:
@Order(Ordered.HIGHEST_PRECEDENCE + 20)
class OnWebApplicationCondition extends SpringBootCondition {
private static final String WEB_CONTEXT_CLASS = "org.springframework.web.context."
+ "support.GenericWebApplicationContext";
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
boolean required = metadata
.isAnnotated(ConditionalOnWebApplication.class.getName());
ConditionOutcome outcome = isWebApplication(context, metadata, required);
if (required && !outcome.isMatch()) {
return ConditionOutcome.noMatch(outcome.getConditionMessage());
}
if (!required && outcome.isMatch()) {
return ConditionOutcome.noMatch(outcome.getConditionMessage());
}
return ConditionOutcome.match(outcome.getConditionMessage());
}
private ConditionOutcome isWebApplication(ConditionContext context,
AnnotatedTypeMetadata metadata, boolean required) {
ConditionMessage.Builder message = ConditionMessage.forCondition(
ConditionalOnWebApplication.class, required ? "(required)" : "");
if (!ClassUtils.isPresent(WEB_CONTEXT_CLASS, context.getClassLoader())) {
return ConditionOutcome
.noMatch(message.didNotFind("web application classes").atAll());
}
if (context.getBeanFactory() != null) {
String[] scopes = context.getBeanFactory().getRegisteredScopeNames();
if (ObjectUtils.containsElement(scopes, "session")) {
return ConditionOutcome.match(message.foundExactly("'session' scope"));
}
}
if (context.getEnvironment() instanceof StandardServletEnvironment) {
return ConditionOutcome
.match(message.foundExactly("StandardServletEnvironment"));
}
if (context.getResourceLoader() instanceof WebApplicationContext) {
return ConditionOutcome.match(message.foundExactly("WebApplicationContext"));
}
return ConditionOutcome.noMatch(message.because("not a web application"));
}
}
实例分析
在了解SpringBoot运作原理和主要的条件注解后,现在分析一个简单的SpringBoot内置的自动配置功能—http的编码配置。
我们在常规的项目中是在web.xml中配置filter,如:
web.xml
<filter>
<filter-name>CharacterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
param>
param>
<param-name>forceEncodingparam-name>
<param-value>trueparam-value>
param>
filter>
自动配置要满足两个条件:
(1)能配置CharacterEncodingFilter这个bean.
(2)能配置encoding和forceEncoding这两个参数
1.配置参数
上一张章讲了类型安全的配置,SpringBoot也是基于这一点配置的,
这里的配置可以在application.properties中直接设置,也可以这样,源码如下:
import java.nio.charset.Charset;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix="spring.http.encoding")
public class HttpEncodingProperties {
public static final Charset DEFAULT_CHAESET=Charset.forName("UTF-8");
private Charset charset = DEFAULT_CHAESET;
private boolean force=true;
public Charset getCharset() {
return charset;
}
public void setCharset(Charset charset) {
this.charset = charset;
}
public boolean isForce() {
return force;
}
public void setForce(boolean force) {
this.force = force;
}
}
代码解释:
在application.properties直接配置的时候前缀为spring.http.encoding;
默认编码方式为UTF-8,若修改可以配置spring.http.encoding.charset=编码;
设置forceEncoding默认为true,若修改可以配置spring.http.encoding.force=false;
配置bean
通过条用上述配置,并根据条件配置CharacterEncodingFilter的bean,源码如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.filter.OrderedCharacterEncodingFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CharacterEncodingFilter;
@Configuration
@EnableConfigurationProperties(HttpEncodingProperties.class)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix="spring.http.encoding",value="enabled",matchIfMissing=true)
public class HttpAutoEncodingBean {
@Autowired
private HttpEncodingProperties httpEncodingProperties;
public CharacterEncodingFilter characterEncodingFilter(){
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.httpEncodingProperties.getCharset().name());
filter.setForceEncoding(this.httpEncodingProperties.isForce());
return filter;
}
}
代码解释:
(1)开启属性注入,通过@EnableConfigurationProperties声明,使用@Autowired注入。
(2)当CharacterEncodingFilter在类路径的条件下、
(3)当设置spring.http.encoding=enabled的配置条件下,如果没有配置则默认为true,即条件符合。
(4)像java配置的方式配置CharacterEncodingFilter这个bean.
(5)当容器中没有这个bean的时候新建bean。
本章Springboot运行原理介绍完毕,下次介绍SpringBoot的web开发,SpringBoot结合redis,Docker等集成开发。