1、从源码角度看spring boot 自动配置
SpringApplication application = new SpringApplication(HelloApplication.class);
这个方法调用的是
public SpringApplication(Object... sources) {
initialize(sources);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
this.webEnvironment = deduceWebEnvironment();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
getSpringFactoriesInstances方法最终最重要的调用是:
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);
}
}
而 FACTORIES_RESOURCE_LOCATION=META-INF/spring.factories
这个其实就是一些自动配置类,如果满足条件就创建配置类,加载配置。这个其实就是spring boot根据jar包自动配置的原理。
2.SpringApplication run方法
在refreshContext中,有这么一系列过程,这个就是springIOC构建过程
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
}
在invokeBeanFactoryPostProcessors
这个方法中会将额外的bean给加入进来,这个方法就是bean factory级别的后置处理器
3、模拟自动配置
3.1属性类
package cn.itcast.springboot.demo.auto;
import org.springframework.stereotype.Component;
/**
* 创建真正的bean需要的属性类
* 2018年4月15日
*
*/
@Component
public class HelloProperties {
private String msg="default";//现在我们在配置文件写hello.msg=world,因为简单就不再展示;如果那么默认为default.
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
3.2 spring需要管理的bean
package cn.itcast.springboot.demo.auto;
public class HelloService {
private String msg = "service";//如果自动配置没有读入成功,那么为默认值
public String say() {
return "hello " + msg;
}//为我们服务的方法
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
3.4 模拟spring boot的自动配置类
它主要负责把HelloProperties 的属性注入到HelloService 中去
package cn.itcast.springboot.demo.auto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration //配置类
@ConditionalOnClass(HelloService.class)//当类路径存在这个类时才会加载这个配置类
public class HelloAutoConfiguration {
@Autowired
private HelloProperties helloProperties;
@Bean
@ConditionalOnMissingBean(HelloService.class)//如果没有我们的自定义Bean那么才会自动配置一个新的Bean
public HelloService auto(){
HelloService helloService =new HelloService();
helloService.setMsg(helloProperties.getMsg());
return helloService;
}
}
通过上面三步在spring容器中就创建了 HelloService ,并且把属性都自动配置好了