一、前言
话说最近咱们组疯狂招人中,组里的几位资深大佬在疯狂面试,从早到晚就是在语音和视频,昨晚要加班,下楼跟大手子们去吃饭,聊起面试情况,一位大佬VV哥开始疯狂输出:“我这面试一天,基本上没几个能把Spring的加载过程说清楚的,基本上一问就支支吾吾,现在这API调用工程师太多了”,另一位大佬脏脏哥疯狂附和,我在一边听到流下了没有技术的“冷汗”,这......不就是说的我嘛,每天写写业务代码,调调接口,写写SQL,搞搞TestCase,属实是最底层的搬砖工,疯狂扒拉两口饭,立马逃离大型审判现场,跑到工位坐下开始 看!源!码!整活~菜狗要翻身!
二、体系
那其实讲到Spring,我们可以这么看:
因为Spring 最初利用“工厂模式”( DI )和“代理模式”( AOP )解耦应用组件。大家觉得挺好用,于是按照这种模式搞了一个 MVC 框架(一些用 Spring 解耦的组件),用开发 web 应用( SpringMVC)。然后呢,又发现每次开发都要搞很多依赖,写很多样板代码很麻烦,那就很烦躁了,于是乎大牛们就搞了一些懒人整合包( starter ),这套玩意就是 Spring Boot ,具体介绍如下:
- Spring是一个一站式的轻量级的java开发框架,核心是控制反转(IOC)和面向切面(AOP),针对于开发的WEB层(springMvc)、业务层(Ioc)、持久层(jdbcTemplate)等都提供了多种配置解决方案;
- SpringMVC是spring基础之上的一个MVC框架,主要处理web开发的路径映射和视图渲染,涵盖面包括前端视图开发、文件配置、后台接口逻辑开发等,XML、config等配置相对比较繁琐复杂,属于spring框架中WEB层开发的一部分;,
- Spring Boot使用了默认大于配置的理念,集成了快速开发的Spring多个插件,同时自动过滤不需要配置的多余的插件,简化了项目的开发配置流程,一定程度上取消xml配置,是一套快速配置开发的脚手架,能快速开发单个微服务;
三、开搞开搞
废话不多说了,现在就跟大家来一次对Spring的源码追踪一波,本菜狗今天就要看一看Spring到底是怎么进行的初始化的,它如何创建的bean,我们这次就从spring-boot-1.5.13进行追踪一步步往下看吧;
1.默认的spring启动器,直接从这个地儿进去,没毛病:
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}复制代码
2.这里创建了一个SpringApplication,执行了一个run方法,返回的是一个ConfigurableApplicationContext,这只是一个接口,根据他的命名来看的话,是一个可配置的应用上下文对象;
下面的run方面看起来就是我们要看的重点吧?Emmmm....不慌不慌,继续往下点就完事了;
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified source using default settings.
* @param source the source to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/public static ConfigurableApplicationContext run(Object source, String... args) {
return run(new Object[] { source }, args);
}
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified sources using default settings and user supplied arguments.
* @param sources the sources to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}复制代码
3.进去run方法后,哦豁,这一大堆玩意儿,也不知道这都是些啥,哎,硬着头皮往下看吧,冲!兄弟们!
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
//参数封装,在命令行下启动应用带的参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}复制代码
3.嗨呀,乍一看好像也就这么些东西,核心的东西都在try{}里面,我们一个个看,前面几行就是获取args参数和准备获取一些环境配置的东西,问题不大;
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);复制代码
4.接下来,嘿,好家伙,开始创建context对象了,看到context = createApplicationContext这行;
context = createApplicationContext();复制代码
然后进入,因为我们刚刚在创建ConfigurableApplicationContext时并没有给 context赋值,所以此时context = null,那么便会创建指定的两个applicationContext中的一个,返回一个刚刚创建的context,这个context便是我们的基础,因为咱们现在为web环境,所以创建的context为 AnnotationConfigEmbeddedWebApplicationContext。
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
contextClass = Class.forName(this.webEnvironment
? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework."
+ "boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext";
private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
复制代码
5.这些事干完之后,就到了准备上下文了;
prepareContext(context, environment, listeners, applicationArguments,printedBanner);
复制代码
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//设置context上下文的environment,简单 设置环境相关的配置呗
context.setEnvironment(environment);
// 应用上下文后处理
postProcessApplicationContext(context);
//在context refresh之前,对其应用ApplicationContextInitializer
applyInitializers(context);
// 上下文准备(这个里面是空实现,这是Spring预留扩展用的)
listeners.contextPrepared(context);
// 打印启动日志和启动应用的Profile
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);
}复制代码
6.上面这些看完好像也没啥,接下来,重头戏应该要来了吧;
refreshContext(context);复制代码
这个方法好像有点狠,看着架势是用来准备容器和刷新应用上下文的,咱们点进去看看;
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}复制代码
诶,还有个方法,继续点进去;
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}复制代码
Emmmmm...乖乖,都是AbstractApplicationContext.class是这个玩意在从中作梗,咱们继续进去!冲!
PS:只要我们进入了refresh(context)这个方法,不管进入哪一个实现类,最终进入的都是AbstractApplicationContext.java这个类:
来到了我们的核心,AbstractApplicationContext类,refresh方法就很贴心,里面每个方法干了啥都有注释,这就很舒服,减少了咱们理解的难度(这时候坐我旁边的粉粉同学看到了就开始小声bb:这英文注释就很烦,在下立***势回怼:快,赶紧装个翻译插件去,快,跑步前进~);
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//初始化一些配置属性,验证配置文件
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//简单的获取beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//将context中的一些属性设置到beanFactory中
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//这个地方空实现,也没干啥,Spring预留的扩展
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//解析配置文件、生成所有的beanDefinitions
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//分类、排序、注册(注入)所有的BeanPostProcessors,用于处理 bean 的初始化流程
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//这玩意就是用来做国际化的
initMessageSource();
// Initialize event multicaster for this context.
//注册 applicationEventMulticaster SingletonBean
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//这里主要创建和初始化容器
onRefresh();
// Check for listener beans and register them.
//检查***bean并注册它们
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//主要是初始化非懒加载单例
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//大功告成,然后开启Web容器
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
//销毁一波
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
//清除一些缓存
resetCommonCaches();
}
}
}复制代码
上面这些代码总结一波:
其实上面的方法中,我们需要比较注意的地方有两个,其实加载bean主要是在这两个方法里面取做的,我们看代码:
1.invokeBeanFactoryPostProcessors(beanFactory);
2.finishBeanFactoryInitialization(beanFactory);
我们进入invokeBeanFactoryPostProcessors,然后继续走着,找到这一行
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());复制代码
然后继续在这个方法中找到
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);复制代码
进入到该方法内部里面之后,有一个循环,进入内部方法 :
postProcessor.postProcessBeanDefinitionRegistry(registry)
此时传入的registry就是我们context中的beanfactory,因为其实现了BeanDefinitionRegistry接口,而此时的postProcessor实现类为ConfigurationClassPostProcessor.java
/**
* Derive further bean definitions from the configuration classes in the registry.
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}复制代码
进入之后直接看最后面的一个方法,名称为processConfigBeanDefinitions(registry),翻译一波就是用来配置beanDefinitions的流程。
OK,我们继续点进去,这里代码过于长,咱们就不贴了8~~~(偷一波懒);
在processConfigBeanDefinitions(registry)里,在301行代码会获取一个解析器,代码如下:
ConfigurationClassParser parser = new ConfigurationClassParser( --301行
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);复制代码
parser.parse(candidates); --308行复制代码
然后308行会执行parser的parse方法,进入parse方法之后,会发现内层还有parse方法,不要紧,继续进入内层的parse,然后发现有个for循环;
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}复制代码
protected final void parse(String className, String beanName) throws IOException {
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
processConfigurationClass(new ConfigurationClass(reader, beanName));
}
protected final void parse(Class<?> clazz, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(clazz, beanName));
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}复制代码
注意!这里有3个parse方法,每个方法里面都执行了下面这个方法;
processConfigurationClass(new ConfigurationClass(metadata, beanName));
复制代码
然后我们继续往下走,在processConfigurationClass(ConfigurationClass configClass)方法内,有一个do循环
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}复制代码
我们继续进去看看,这个时候,出现了许多我们常用的注解,Spring会找到这些注解,并对它们进行解析。我们看代码:
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}复制代码
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());复制代码
进入 this.componentScanParser.parse,直接进入结尾的scannner.doScan
return scanner.doScan(StringUtils.toStringArray(basePackages));
然后就会开始扫描basePackages,并将扫描到的bean生成一个一个BeanDefinitionHolder,BeanDefinitionHolder中包含有我们bean的一些相关信息、以及Spring赋予其的额外信息
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}复制代码
然后就开始调用如下方法将bean注册到BenFactory中!
registerBeanDefinition(definitionHolder, this.registry);复制代码
OK,注册完后,invokeBeanFactoryPostProcessors(beanFactory)这个方法也算是使命结束,这个时候我们直接跳到finishBeanFactoryInitialization(beanFactory)这个方法,我们点进去:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}复制代码
到这个阶段了,我们要开始创建bean的实例了,我们找到下面的代码:
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}复制代码
进入getBean!
@Override
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}复制代码
再进getBean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}复制代码
哎哟,我去,还有一层啊,有点烦!再进去!
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}复制代码
然后我们继续哐哐哐往下整吧(任重道远啊!好多层!)
从上面的代码找到这一行,看名字就是创建Bean,我们继续点进去
prototypeInstance = createBean(beanName, mbd, args);复制代码
这个方法进去后,找到下面这行,继续进去(要疯了,兄弟们)
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
复制代码
OKKKKK,这个进去后还有,找到下面代码:
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}复制代码
然后再进入createBeanInstance方法,找到下面的代码
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}复制代码
进入autowireConstructor(很明显,注解构造器),然后.....Emmm....里面还有,我们在里面找到下面这段代码:
if (System.getSecurityManager() != null) {
final Constructor<?> ctorToUse = constructorToUse;
final Object[] argumentsToUse = argsToUse;
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
}
}, beanFactory.getAccessControlContext());
}
else {
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}复制代码
啥也别说了,继续进入这个方法,好像到一个工具类了,看到希望了!!!
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
if (bd.getMethodOverrides().isEmpty()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
ReflectionUtils.makeAccessible(ctor);
return null;
}
});
}
return BeanUtils.instantiateClass(ctor, args);
}
else {
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}复制代码
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor);
return ctor.newInstance(args);
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
}
}复制代码
@CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
}复制代码
感动落泪,终于到了Spring bean加载的核心了!对!反射!我们最后会发现是通过反射newInstance取得的对象实例:
获取到对象实例之后,我们要干啥?填充一波 调用populateBean方法!
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}复制代码
继续点进去,进入后便能看到和我们平时代码对应的条件了,例如byType注入、byName注入:
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}复制代码
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}复制代码
这个时候,这一行代码,就是进行依赖注入的地方了!
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);复制代码
这个时候,我们一点,发现有很多实现类,感觉我们平时项目里面@Autowired注解用得多一点,我们就选AutowiredAnnotationBeanPostProcessor这个类吧,点开看看:
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;复制代码
看findAutowiringMetadata这个方法名应该是获取元信息,获取完后,再调用:
metadata.inject(bean, beanName, pvs);复制代码
@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName)) {
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}复制代码
激动啊,这个莫非就是传说中替我们做的set方法??最后完成注入?
field.set(bean, value);
四、总结
写完这个之后,总体对Spring加载的过程有了更深入的理解,在看源码的过程中,也有很多自己不理解的东西,也综合了很多信息来帮忙自己理解和完成这次文章,相信大哥们看完可能会发现一些错误或者理解不一致处,欢迎指出,共同进步!