0
过往的开发教训通知咱们,大部分的配置其实应用默认值即可,并不需要手动逐条配置,springboot的外围性能之一就是尽可能地帮忙咱们进行主动配置,同时在application.yml配置文件中提供了批改默认值的入口。
本文通过结构一个主动配置类来探索其原理。
最终代码地址:https://github.com/RonaldBBB/...
1.对于@ConditionalOnMissingBean的纳闷
之前始终纳闷,Bean被退出容器的程序是否会影响@ConditionalOnMissingBean的行为。
事实上首先,通过主动配置将Bean退出容器的行为,总是产生在利用自身的配置类的行为之后;其次依据@ConditionalOnMissingBean本身的正文:
The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only. If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after.
能够晓得如果通过主动配置退出容器的Bean之间存在先后关系,必须严格地应用@AutoConfigureBefore @AutoConfigureAfter进行规定。
2
需要:
应用主动配置类向容器中装载一个School Bean,School蕴含List<Student>的依赖。使用者无奈通过application.yml笼罩默认配置。
剖析:
和咱们日常在@Configuration类中应用@Bean装载Bean惟一的区别在于,须要在META-INF/spring.factories中增加自定义的配置类,以让AutoConfigurationImportSelector能够扫描到该主动配置类。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.zyf.autoconfigure.SchoolAutoConfiguration
具体代码:
为了切合惯例架构,将须要主动配置的类和主动配置类放到了不同的jar包中.
school用来寄存被主动装载的类.
@Data@NoArgsConstructor@AllArgsConstructorpublic class School { private String name; private List<Student> students;}
school-autoconfigure用来寄存主动配置类.
@Slf4j@Configurationpublic class SchoolAutoConfiguration { @Bean public School school(){ School school = new School(); List<Student> students = new ArrayList<>(); students.add(new Student("Fred")); students.add(new Student("Frank")); school.setStudents(students); school.setName("AutoConfigured School"); log.info(school.toString()); return school; }}
autoconfigure-demo只有一个启动类,从日志中能够看到Bean被主动装载的信息.
@SpringBootApplicationpublic class AutoconfigureDemoApplication { public static void main(String[] args) { SpringApplication.run(AutoconfigureDemoApplication.class, args); }}
3
需要:
- 在上一节的根底上,实现能够从application.xml中笼罩默认配置(school.students-names,school.name).
- 在应用程序中通过@Bean形式装载的Bean必须可能笼罩主动配置中装载的Bean.
剖析
须要一个@ConfigurationProperties类SchoolProperties来承受applicaiton.yml中传入的自定义配置信息.
在主动配置类中导入SchoolProperties中的信息,如果信息存在则应用,不存在则应用默认配置.
欠缺主动生成的META-INF/spring-configuration-metadata,提醒默认值.对于该文件参见官网文档:https://docs.spring.io/spring...
- 通过@ConditionalOnClass @ConditionalOnMissingBean @ConditionalOnProperty欠缺主动配置的流程,使得应用程序中通过@Bean形式装载的Bean可能笼罩主动配置中装载的Bean.
具体代码
@Data@NoArgsConstructor@AllArgsConstructor@ConfigurationProperties(prefix = "school")public class SchoolProperties { private String name; private List<String> studentsNames;}
@Slf4j@Configuration@ConditionalOnClass(School.class)@EnableConfigurationProperties(SchoolProperties.class)public class SchoolAutoConfiguration { @Autowired private SchoolProperties schoolProperties; @Bean @ConditionalOnMissingBean(School.class) @ConditionalOnProperty(name = "school.enabled", havingValue = "true", matchIfMissing = true) public School school(){ School school = new School(); List<Student> students = new ArrayList<>(); if(schoolProperties.getStudentsNames()!=null){ for (String name : schoolProperties.getStudentsNames()) { students.add(new Student(name)); } }else{ students.add(new Student("Fred")); students.add(new Student("Frank")); } school.setStudents(students); if(StringUtils.hasText(schoolProperties.getName()))school.setName(schoolProperties.getName()); else school.setName("School Generated By AutoConfigure"); log.info("generated by autoconfigure "+school.toString()); return school; }}