情况
本文基于Spring Boot版本1.3.3, 利用了spring-boot-starter-web。
设置完成后,软件开发,编写了代码如下:
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } @RestController public class RootController { public static final String PATH_ROOT = "/"; @RequestMapping(PATH_ROOT) public String welcome() { return "Welcome!"; } }
固然只有几行代码,可是这已经是一个完整的Web措施,当会见url的path部门为”/”时,返回字符串”Welcome!”。
首先是一个很是普通的java措施进口,一个切合约定的静态main要领。在这个main要领中,挪用了SpringApplication的静态run要领,并将Application类工具和main要领的参数args作为参数通报了进去。
然后是一个利用了两个Spring注解的RootController类,我们在main要领中,没有直接利用这个类。
SpringApplication类的静态run要领
以下代码摘自:org.springframework.boot.SpringApplication public static ConfigurableApplicationContext run(Object source, String... args) { return run(new Object[] { source }, args); } public static ConfigurableApplicationContext run(Object[] sources, String[] args) { return new SpringApplication(sources).run(args); }
在这个静态要领中,建设SpringApplication工具,并挪用该工具的run要领。
结构SpringApplication工具
以下代码摘自:org.springframework.boot.SpringApplication public SpringApplication(Object... sources) { initialize(sources); } private void initialize(Object[] sources) { // 为成员变量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(); }
结构函数中挪用initialize要领,初始化SpringApplication工具的成员变量sources,webEnvironment,initializers,listeners,mainApplicationClass。sources的赋值较量简朴,就是我们传给SpringApplication.run要领的参数。剩下的几个,我们依次来看看是怎么做的。
首先是webEnvironment:
以下代码摘自:org.springframework.boot.SpringApplication private boolean webEnvironment; private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext" }; private void initialize(Object[] sources) { ... // 为成员变量webEnvironment赋值 this.webEnvironment = deduceWebEnvironment(); ... } private boolean deduceWebEnvironment() { for (String className : WEB_ENVIRONMENT_CLASSES) { if (!ClassUtils.isPresent(className, null)) { return false; } } return true; }
可以看到webEnvironment是一个boolean,该成员变量用来暗示当前应用措施是不是一个Web应用措施。那么怎么抉择当前应用措施是否Web应用措施呢,是通过在classpath中查察是否存在WEB_ENVIRONMENT_CLASSES这个数组中所包括的类,假如存在那么当前措施等于一个Web应用措施,反之则否则。
在本文的例子中webEnvironment的值为true。
然后是initializers:
initializers成员变量,是一个ApplicationContextInitializer范例工具的荟萃。 顾名思义,ApplicationContextInitializer是一个可以用来初始化ApplicationContext的接口。
以下代码摘自:org.springframework.boot.SpringApplication private List<ApplicationContextInitializer<?>> initializers; private void initialize(Object[] sources) { ... // 为成员变量initializers赋值 setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class)); ... } public void setInitializers( Collection<? extends ApplicationContextInitializer<?>> initializers) { this.initializers = new ArrayList<ApplicationContextInitializer<?>>(); this.initializers.addAll(initializers); }
可以看到,要害是挪用getSpringFactoriesInstances(ApplicationContextInitializer.class),来获取ApplicationContextInitializer范例工具的列表。
以下代码摘自:org.springframework.boot.SpringApplication private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) { return getSpringFactoriesInstances(type, new Class<?>[] {}); } private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); // Use names and ensure unique to protect against duplicates Set<String> names = new LinkedHashSet<String>( SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }