1.大致预览一下这个方法,方法的入参
context 为AnnotationConfigEmbeddedWebApplicationContext
environment 为 StandardServletEnvironment
listeners 为SpringApplicationRunListeners
applicationArguments 为 DefaultApplicationArguments
printedBanner 为SpringApplicationBannerPrinter$PrintedBanner
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// Load the sources
Set<Object> sources = getSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[sources.size()]));
listeners.contextLoaded(context);
}
2.context.setEnvironment(environment); 这个很简单
3.postProcessApplicationContext(context); 进入这个方法,
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
if (this.beanNameGenerator != null) {
context.getBeanFactory().registerSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
}
if (this.resourceLoader != null) {
if (context instanceof GenericApplicationContext) {
((GenericApplicationContext) context)
.setResourceLoader(this.resourceLoader);
}
if (context instanceof DefaultResourceLoader) {
((DefaultResourceLoader) context)
.setClassLoader(this.resourceLoader.getClassLoader());
}
}
}
可以resourceLoader 和 beanNameGenerator都为null,此方法相当于什么都没做
4.applyInitializers(context)方法
@SuppressWarnings({ "rawtypes", "unchecked" })
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
这里就是将之前springApplication对象中initializers进行遍历,执行initializer.initialize(context);方法
其中 initializers以SharedMetadataReaderFactoryContextInitializer为例
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.addBeanFactoryPostProcessor(
new CachingMetadataReaderFactoryPostProcessor());
}
这里是执行applicationContext.addBeanFactoryPostProcessor,也就是添加BeanFactoryPostProcessor
5.listeners.contextPrepared(context);这个方法会进入EventPublishingRunListener的contextPrepared,而这个方法特么是个空方法体,又什么也没干
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
}
6.if (this.logStartupInfo) { logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}进入这个方法
context.getParent()为null,他没有父上下文,进入到logStartupInfo(true)
public void logStarting(Log log) {
Assert.notNull(log, "Log must not be null");
if (log.isInfoEnabled()) {
log.info(getStartupMessage());
}
if (log.isDebugEnabled()) {
log.debug(getRunningMessage());
}
}
会打印日志
2019-08-12 11:15:14.835 INFO 24024 --- [ main] com.songhq.ZongHeApplication : Starting ZongHeApplication on SC-201812171309 with PID 24024 (D:\songhaiqiang\code\workspace\my\zonghe\target\classes started by Administrator in D:\songhaiqiang\code\workspace\my\zonghe) 和
2019-08-12 11:17:04.169 DEBUG 24024 --- [ main] com.songhq.ZongHeApplication : Running with Spring Boot v1.5.9.RELEASE, Spring v4.3.13.RELEASE
protected void logStartupProfileInfo(ConfigurableApplicationContext context) {
Log log = getApplicationLog();
if (log.isInfoEnabled()) {
String[] activeProfiles = context.getEnvironment().getActiveProfiles();
if (ObjectUtils.isEmpty(activeProfiles)) {
String[] defaultProfiles = context.getEnvironment().getDefaultProfiles();
log.info("No active profile set, falling back to default profiles: "
+ StringUtils.arrayToCommaDelimitedString(defaultProfiles));
}
else {
log.info("The following profiles are active: "
+ StringUtils.arrayToCommaDelimitedString(activeProfiles));
}
}
}
这个方法会打印
2019-08-12 11:18:44.820 INFO 24024 --- [ main] com.songhq.ZongHeApplication : The following profiles are active: dev
7.进入context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments);这个方法,
这个方法很明显,是在beanfactory手动注入一个springApplicationArguments的单例对象,我们这里看看registerSingleton这个方法,看看具体是如何注入的
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
super.registerSingleton(beanName, singletonObject);
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
if (!this.beanDefinitionMap.containsKey(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames.size() + 1);
updatedSingletons.addAll(this.manualSingletonNames);
updatedSingletons.add(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
if (!this.beanDefinitionMap.containsKey(beanName)) {
this.manualSingletonNames.add(beanName);
}
}
clearByTypeCache();
}
7.1super.registerSingleton(beanName, singletonObject); 进入DefaultSingletonBeanRegistry类中
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
addSingleton(beanName, singletonObject);
}
}
看这个/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);当前只有
{autoConfigurationReport=org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport@37fb0bed}这一个单例对象,所以会走addSingleton这个方法
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
然后一步步返回
8. 走到 if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
},代码很简单,向context注入 一个单例的springBootBanner
9.走到 Set<Object> sources = getSources();
Assert.notEmpty(sources, "Sources must not be empty"); 获取springApplication中的sources
10.进入 load(context, sources.toArray(new Object[sources.size()]));方法
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug(
"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
BeanDefinitionLoader loader = createBeanDefinitionLoader(
getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
loader.load();
}
10.1 if (logger.isDebugEnabled()) {
logger.debug(
"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
打印出日志2019-08-12 19:19:09.017 DEBUG 4068 --- [ main] o.s.boot.SpringApplication : Loading source class com.songhq.ZongHeApplication
10.2 getBeanDefinitionRegistry(context)
private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) {
if (context instanceof BeanDefinitionRegistry) {
return (BeanDefinitionRegistry) context;
}
if (context instanceof AbstractApplicationContext) {
return (BeanDefinitionRegistry) ((AbstractApplicationContext) context)
.getBeanFactory();
}
throw new IllegalStateException("Could not locate BeanDefinitionRegistry");
}
这个方法时获取BeanDefinitionRegistry
继续进入createBeanDefinitionLoader方法
protected BeanDefinitionLoader createBeanDefinitionLoader(
BeanDefinitionRegistry registry, Object[] sources) {
return new BeanDefinitionLoader(registry, sources);
}
再进入构造方法,BeanDefinitionLoader这个类是加载beanDefinition的,也是对AnnotatedBeanDefinitionReader,
ClassPathBeanDefinitionScanner,XmlBeanDefinitionReader 等类的包装
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
this.sources = sources;
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
this.xmlReader = new XmlBeanDefinitionReader(registry);
if (isGroovyPresent()) {
this.groovyReader = new GroovyBeanDefinitionReader(registry);
}
this.scanner = new ClassPathBeanDefinitionScanner(registry);
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
10.3 进入 load.load(),根据sources的不同类型加载不同的load方法,这里用到了方法的重载
这里的sources 是ZhongHeApplication的clazz,走到了 load(Class<?> source)方法,最后走到this.annotatedReader.register(source);方法,进而走registerBean;如下
@SuppressWarnings("unchecked")
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
以这个对象AnnotatedGenericBeanDefinition封装我们的clazz,接着是解析此BeanDefinition的ScopeMetadata ,而一个ScopeMetadata对象里面有有两个默认的属性值,一个作用域的范围,一个是该范围的代理模式
作用域默认为singleton ,ScopedProxyMode默认为ScopedProxyMode.NO,即不创建代理
private String scopeName = BeanDefinition.SCOPE_SINGLETON;
private ScopedProxyMode scopedProxyMode = ScopedProxyMode.NO;
然后将ScopeMetadata对象的scoscoreName赋值给AnnotatedGenericBeanDefinition中的scope属性,此处就是singleton,
接下来进入this.beanNameGenerator.generateBeanName(abd, this.registry)方法,该方法在AnnotationBeanNameGenerator类中
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) {
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
if (StringUtils.hasText(beanName)) {
// Explicit bean name found.
return beanName;
}
}
// Fallback: generate a unique default bean name.
return buildDefaultBeanName(definition, registry);
}
从这个方法的名称上看,就是根据BeanDefinition和BeanDefinitionRegistry 来生成这个bean的名称,
前面已经分析过,BeanDefinition是spring对原始bean的clazz封装和管理,注意还没生成对象,BeanDefinitionRegistry 又是个什么东西,这里具体看看,这里的BeanDefinitionRegistry当然是个接口
这个接口中关于接口的注释大致为:
于保存bean Definition例如rootbeanDefinition和childbeanDefinition的注册表的接口,通常由内部使用AbstractBeanDefinition层次结构的BeanFactory实现,可见他和重要,被BeanFactory实现
从名字上看他就是注册BeanDefinition的作用,这里的实现类是AnnotationConfigEmbeddedWebApplicationContext,正是前面的context ,该上下文也实现了BeanDefinitionRegistry接口
接下来看看 AnnotationBeanNameGenerator这个类,该类在类上的注释的大致意思是
该类是为了@Component注解实现的,也支持@ManagedBean 等注解
接下来要看 determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);方法
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
AnnotationMetadata amd = annotatedDef.getMetadata();
Set<String> types = amd.getAnnotationTypes();
String beanName = null;
for (String type : types) {
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
if (isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
Object value = attributes.get("value");
if (value instanceof String) {
String strVal = (String) value;
if (StringUtils.hasLength(strVal)) {
if (beanName != null && !strVal.equals(beanName)) {
throw new IllegalStateException("Stereotype annotations suggest inconsistent " +
"component names: '" + beanName + "' versus '" + strVal + "'");
}
beanName = strVal;
}
}
}
}
return beanName;
}
这里先是拿到了该clazz上的所有注解,这里ZongHeApplication.class,上的注解有@SpringBootApplication和
@EnableAspectJAutoProxy(proxyTargetClass = true)两个注解
至于怎么拿到的,最原始的方法为在java.lang.Class类中,而ZongHeApplication.class即是Class的一个实例
public Annotation[] getAnnotations() {
return AnnotationParser.toArray(annotationData().annotations);
}
至于继续是怎么走的。这里我们不再深究,继续往下走,第一次遍历的是注解org.springframework.boot.autoconfigure.SpringBootApplication
进入isStereotypeWithNameValue方法,该方法就是判断你是否是Stereotype并且注解里面有value属性,也就是说你是否制定生成对象的对象名,很明显没有
第二次是这个注解org.springframework.context.annotation.EnableAspectJAutoProxy,很明显也没有
protected boolean isStereotypeWithNameValue(String annotationType,
Set<String> metaAnnotationTypes, Map<String, Object> attributes) {
boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
(metaAnnotationTypes != null && metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME)) ||
annotationType.equals("javax.annotation.ManagedBean") ||
annotationType.equals("javax.inject.Named");
return (isStereotype && attributes != null && attributes.containsKey("value"));
}
没有制定生成对象的名字,就会走return buildDefaultBeanName(definition, registry);方法最后会进入这个方法
protected String buildDefaultBeanName(BeanDefinition definition) {
String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
return Introspector.decapitalize(shortClassName);
}
他的shortClassName为ZongHeApplication,然后将的首字母小写,最后得到zongHeApplication
得到名称,和将所对应的beanDefinition处理好了,就轮到register取注册该bean了,该处的register为AnnotationConfigEmbeddedWebApplicationContext也是GenericApplicationContext的子类
在GenericApplicationContext中有如下方法
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry
//---------------------------------------------------------------------
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
这里嫁接到了this.beanFactory.registerBeanDefinition(beanName, beanDefinition);这里的beanFactory是DefaultListableBeanFactory
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
可以看出这里还是把它放在一map中去了,而且并没有实例化出来,至此第10步分析完毕
11.进入 listeners.contextLoaded(context);
再进入
public void contextLoaded(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.contextLoaded(context);
}
}
再进入,下面的方法先将listener处理一下,如果是ApplicationContextAware就把context赋值给他,然后广播事件ApplicationPreparedEvent
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener<?> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
context.addApplicationListener(listener);
}
this.initialMulticaster.multicastEvent(
new ApplicationPreparedEvent(this.application, this.args, context));
}
最终又走到listener.onApplicationEvent(event);方法上,与之前类似
自此prepareContext方法分析完毕
总结一下,大致对Context进行配置,然后注入一些bean,还有就是广播了一个ApplicationPreparedEvent事件