@ConfigurationProperties(
prefix = “server”,
ignoreUnknownFields = true
)
public class ServerProperties {
private Integer port;
private InetAddress address;
此时当我们启动springboot的时候
@SpringBootApplication
public class App
{
public static void main( String[] args ){
SpringApplication.run(App.class , args);
}
}
会加载App.class ,在App.class上面 有一个注解 @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 {
此时有一个@EnableAutoConfiguration 自动装配注解 我们查看这个注解 这也是一个复合注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = “spring.boot.enableautoconfiguration”;
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
此时发现有一个import注解 用来导入AutoConfigurationImportSelector类 这个类就是自定装配干活的类
在AutoConfigurationImportSelector类中 有一个函数
protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, “No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.”);
return configurations;
}
这个方法用来加载配置项的信息 在这个方法中
public static List loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
又调用了 loadSpringFactories 方法 在 loadSpringFactories 方法中
有一个加载配置的代码
Enumeration urls = classLoader.getResources(“META-INF/spring.factories”);
而 这个 “META-INF/spring.factories” 就是我们导入的框架中 都有的一个配置文件
此时我们找到了配置文件spring.factories文件 并且打开 发现里面是这样的东西
Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
这是当前第三方框架和boot自己的自动装配类,也就是说 springboot读取的就是别人写好的自动配置的类,别人写好的类 将这个类名写到了
spring.factories文件中, 而springboot在启动的时候 加载的 @SpringBootApplication注解就是用来读取 spring.factories文件中的类 并且让其执行的
当有一些配置无法自动自配 需要程序员手动配置的时候
我们只需要在 application.properties中配置
然后会有一个类读取配置文件信息
@ConfigurationProperties(
prefix = “mybatis”
)
public class MybatisProperties {
而 MybatisAutoConfiguration 又会读取MybatisProperties 中的信息
@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties({MybatisProperties.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class})
public class MybatisAutoConfiguration implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(MybatisAutoConfiguration.class);
private final MybatisProperties properties;
private final Interceptor[] interceptors;
private final TypeHandler[] typeHandlers;
private final LanguageDriver[] languageDrivers;
private final ResourceLoader resourceLoader;
private final DatabaseIdProvider databaseIdProvider;
private final List configurationCustomizers;
public MybatisAutoConfiguration(MybatisProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider, ObjectProvider<TypeHandler[]> typeHandlersProvider, ObjectProvider<LanguageDriver[]> languageDriversProvider, ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
this.properties = properties;
this.interceptors = (Interceptor[])interceptorsProvider.getIfAvailable();
this.typeHandlers = (TypeHandler[])typeHandlersProvider.getIfAvailable();
this.languageDrivers = (LanguageDriver[])languageDriversProvider.getIfAvailable();
this.resourceLoader = resourceLoader;
this.databaseIdProvider = (DatabaseIdProvider)databaseIdProvider.getIfAvailable();
this.configurationCustomizers = (List)configurationCustomizersProvider.getIfAvailable();
}