6.5 SpringBoot的核心:SpringBoot的运行原理
6.5 常识
1.SpringBoot的自动配置是基于
—> Spring4.X提供了基于条件来配置Bean的能力
2.通过两种方式来查看当前项目启用和未启用的自动配置
2.1 java -jar xxx.jar --debug
2.2 在properties中加入debug=true
打开debug的日志
启用的配置
Positive matches:
-----------------
AbstractThymeleafViewResolverConfiguration#thymeleafViewResolver matched:
- @ConditionalOnProperty (spring.thymeleaf.enabled) matched (OnPropertyCondition)
- @ConditionalOnMissingBean (names: thymeleafViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition)
未启用的配置
Negative matches:
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)
除外的配置
Exclusions:
-----------org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
举例:
6.5.1 运作原理(扫描spring.factories里面的自动配置java配置)
1.核心功能是@SpringBootApplication组合注解中的@EnableAutoConfiguration提供的
2.在EnableAutoConfiguration注解了@Import(EnableAutoConfigurationImportSelector.class)
3.在EnableAutoConfigurationImportSelector.class中发父类selectImports中指定了扫描哪些类需要自动配置
-> 最终是SpringFactoriesLoader.loadFactoryNames
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories”;
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<String>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
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,\
6.5 核心注解
1.打开spring.factories里面的任意一条注解
一般都有以下注解
1.1 @ConditionOnBean 当容器中有指定bean的时候
1.2 @ConditionOnClass 类路径下有指定类的条件下
1.3 @ConditionOnExpression 基于SpEL表达式作为判断
1.4 @ConditionOnJava 基于jvm版本作为判断
1.5 @ConditionOnJndi 在JNDI存在的条件下查找指定位置
1.6 @ConditionOnMissingBean 在容器中没有指定Bean的时候
1.7 @ConditionOnMissingClass 在类路径下没有指定类的条件下
1.8 @ConditionOnNotWebApplication 当前项目不是Web项目的条件
1.9 @ConditionOnProperty 指定的属性是否有指定的值
2.0 @ConditionOnResource 类路径下是否有指定的值
2.1 @ConditionOnSingleCandidate 指定Bean在容器中只有一个或者虽然有多个,但是指定了首选Bean
2.2 @ConditionOnWebApplication 在当前的项目是Web项目
示例:
ConditionalOnClass(PersistenceExceptionTranslationPostProcessor.class)
public class PersistenceExceptionTranslationAutoConfiguration {
@Bean
@ConditionalOnMissingBean(PersistenceExceptionTranslationPostProcessor.class)
@ConditionalOnProperty(prefix = "spring.dao.exceptiontranslation", name = "enabled", matchIfMissing = true)
public static PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor(
Environment environment) {
PersistenceExceptionTranslationPostProcessor postProcessor = new PersistenceExceptionTranslationPostProcessor();
postProcessor.setProxyTargetClass(determineProxyTargetClass(environment));
return postProcessor;
}
private static boolean determineProxyTargetClass(Environment environment) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.aop.");
Boolean value = resolver.getProperty("proxyTargetClass", Boolean.class);
return (value != null ? value : true);
}
}