博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
拒绝做菜dog——初探Spring源码,我今天必须讲明白它
阅读量:4131 次
发布时间:2019-05-25

本文共 31463 字,大约阅读时间需要 104 分钟。

一、前言

    话说最近咱们组疯狂招人中,组里的几位资深大佬在疯狂面试,从早到晚就是在语音和视频,昨晚要加班,下楼跟大手子们去吃饭,聊起面试情况,一位大佬VV哥开始疯狂输出:“我这面试一天,基本上没几个能把Spring的加载过程说清楚的,基本上一问就支支吾吾,现在这API调用工程师太多了”,另一位大佬脏脏哥疯狂附和,我在一边听到流下了没有技术的“冷汗”,这......不就是说的我嘛,每天写写业务代码,调调接口,写写SQL,搞搞TestCase,属实是最底层的搬砖工,疯狂扒拉两口饭,立马逃离大型审判现场,跑到工位坐下开始 看!源!码!整活~菜狗要翻身!

二、体系

   那其实讲到Spring,我们可以这么看:

   因为Spring 最初利用“工厂模式”( DI )和“代理模式”( AOP )解耦应用组件。大家觉得挺好用,于是按照这种模式搞了一个 MVC 框架(一些用 Spring 解耦的组件),用开发 web 应用( SpringMVC)。然后呢,又发现每次开发都要搞很多依赖,写很多样板代码很麻烦,那就很烦躁了,于是乎大牛们就搞了一些懒人整合包( starter ),这套玩意就是 Spring Boot ,具体介绍如下:

  1. Spring是一个一站式的轻量级的java开发框架,核心是控制反转(IOC)和面向切面(AOP),针对于开发的WEB层(springMvc)、业务层(Ioc)、持久层(jdbcTemplate)等都提供了多种配置解决方案;  
  2. SpringMVC是spring基础之上的一个MVC框架,主要处理web开发的路径映射和视图渲染,涵盖面包括前端视图开发、文件配置、后台接口逻辑开发等,XML、config等配置相对比较繁琐复杂,属于spring框架中WEB层开发的一部分;,
  3. 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 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:这英文注释就很烦,在下立马强势回怼:快,赶紧装个翻译插件去,快,跑步前进~);

@Overridepublic 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. */@Overridepublic 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
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
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
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!

@Overridepublic Object getBean(String name) throws BeansException {   assertBeanFactoryActive();   return getBeanFactory().getBean(name);}复制代码

再进getBean

@Overridepublic Object getBean(String name) throws BeansException {   return doGetBean(name, null, null, false);}复制代码

哎哟,我去,还有一层啊,有点烦!再进去!

protected 
T doGetBean( final String name, final Class
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
() { @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() { @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() { @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);}复制代码

啥也别说了,继续进入这个方法,好像到一个工具类了,看到希望了!!!

@Overridepublic 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() { @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 instantiateClass(Constructor
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()); }}复制代码
@CallerSensitivepublic 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这个类吧,点开看看:

@Overridepublic 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
autowiredBeanNames = new LinkedHashSet
(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加载的过程有了更深入的理解,在看源码的过程中,也有很多自己不理解的东西,也综合了很多信息来帮忙自己理解和完成这次文章,相信大哥们看完可能会发现一些错误或者理解不一致处,欢迎指出,共同进步!

 

转载地址:http://zyfvi.baihongyu.com/

你可能感兴趣的文章
Objective-C 基础入门(一)
查看>>
Flutter Boost的router管理
查看>>
iOS开发支付集成之微信支付
查看>>
C++模板
查看>>
【C#】如何实现一个迭代器
查看>>
【C#】利用Conditional属性完成编译忽略
查看>>
VUe+webpack构建单页router应用(一)
查看>>
(python版)《剑指Offer》JZ01:二维数组中的查找
查看>>
Spring MVC中使用Thymeleaf模板引擎
查看>>
PHP 7 的五大新特性
查看>>
深入了解php底层机制
查看>>
PHP中的stdClass 【转】
查看>>
XHProf-php轻量级的性能分析工具
查看>>
OpenCV gpu模块样例注释:video_reader.cpp
查看>>
就在昨天,全球 42 亿 IPv4 地址宣告耗尽!
查看>>
Mysql复制表以及复制数据库
查看>>
Linux分区方案
查看>>
如何使用 systemd 中的定时器
查看>>
git命令速查表
查看>>
linux进程监控和自动重启的简单实现
查看>>