From a1b6b2cfce9232b9cd5fba7f8b4f5c4bd3a6fa57 Mon Sep 17 00:00:00 2001 From: youthlql <1826692270@qq.com> Date: Mon, 6 Dec 2021 22:45:28 +0800 Subject: [PATCH] =?UTF-8?q?spring=E6=BA=90=E7=A0=81=E7=B3=BB=E5=88=97-?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=AC=AC=E4=B8=80=E7=AF=87=E6=96=87=E7=AB=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 +- .../01.第1章-Spring源码纵览.md | 1980 +++++++++++++++++ 2 files changed, 1989 insertions(+), 1 deletion(-) create mode 100644 docs/spring-sourcecode-v1/01.第1章-Spring源码纵览.md diff --git a/README.md b/README.md index 5955643..ee22070 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,15 @@ -## 源码 +## 源码【12.6开始更新】 + + + +[01.第1章-Spring源码纵览](docs/spring-sourcecode-v1/01.第1章-Spring源码纵览.md) + + + + # Netty diff --git a/docs/spring-sourcecode-v1/01.第1章-Spring源码纵览.md b/docs/spring-sourcecode-v1/01.第1章-Spring源码纵览.md new file mode 100644 index 0000000..84b6581 --- /dev/null +++ b/docs/spring-sourcecode-v1/01.第1章-Spring源码纵览.md @@ -0,0 +1,1980 @@ +--- +title: Spring源码系列-第1章-Spring源码纵览 +tags: + - Spring源码 +categories: + - Spring + - 源码V1 +keywords: Spring,框架 +description: Spring源码纵览 +cover: 'https://cdn.jsdelivr.net/gh/youthlql/youthlql/img/spring.png' +abbrlink: 599156d +date: 2021-12-06 23:21:58 +--- + + + + + +# 必读 + +1. 源码是循循渐进的,前面我会省略中间很多目前不需要深入的代码,所以会看起来代码比较少。省略的地方我会打上这样的标识 + +```java +// ... +或者 +// ...... +``` + +2. 如果没打也不代表我没省略,可能是忘记了,不要看懵了。 + +# 第1章-Spring源码纵览 + +## 概述 + +Spring源码纵览这一节,主要是先了解下Spring的一些核心东西,所以前后可能关联不是特别深,跳跃性比较大,往后看就行。 + +## 简单的继承关系图 + + + + + +- **蓝色实线箭头**是指继承关系 +- **绿色虚线箭头**是指接口实现关系 +- **绿色虚线箭头**是指接口继承关系 + +- 注解版使用AnnotationConfigApplicationContext +- XML版使用ClassPathXmlApplicationContext + + + +## Spring框架整体流程 + + + +1. 不管是用XML还是注解也好,最终形成一份组件或者功能的配置清单。 +2. Spring用Resource来表示所有的资源 +3. 这些资源被ResourceLoader加载然后交给BeanDefinitionReader解析成BeanDefinition(Bean的定义信息)。BeanDefinition就是一个对象的图纸,模板。 +4. 然后将这些BeanDefinition放入到BeanDefinitionRegistry(其实就是一个Map)里,等待以后使用。 +5. 最后经过漫长的过程,根据BeanDefinition创建一个个的对象。 + + + +## 核心组件接口分析 + +**基础接口** + +```java +Resource+ResourceLoader +BeanFactory +BeanDefinition +BeanDefinitionReader +BeanDefinitionRegistry +ApplicationContext +Aware +``` + +**生命周期-后置处理器** + +```java +BeanFactoryPostProcessor +InitializingBean +BeanPostProcessor +``` + + + +### Resource资源 + +#### 方法 + +快捷键:ctrl+F12 看类的方法 + + + +#### 实现类 + +快捷键:ctrl+h 查看接口实现类 + + + + + +1. ContextResource:表示可以拿Web环境的资源 +2. HttpResource:可以从网络中拿到资源 + +3. WritableResource: + 1. FileSystemResource:可以从文件系统拿到资源 + 2. FileUrlResource:URL就是统一资源定位符的意思;URL可以定位到网络,磁盘,等任何你想定位到的位置;表示Spring几乎可以从任何地方拿到资源。 +4. AbstractResource + 1. ByteArrayResource:从byte数组拿到资源 + 2. InputStreamResource:从Input流中拿到资源 +5. 综合来说Spring几乎可以从任何地方拿到资源。 + +### ResourceLoader资源加载器 + +此类的源码开头有这样一句话,Strategy interface(策略接口),显然用到了策略模式。策略体现在哪个地方,我们下面再说。 + +> Strategy interface for loading resources (e.g., class path or file systemresources) + +#### 方法 + +```java +/** + * Strategy interface(策略接口) for loading resources (e.g., class path or file system + * resources). An {@link org.springframework.context.ApplicationContext} + * is required to provide this functionality plus extended + * {@link org.springframework.core.io.support.ResourcePatternResolver} support. + * + *

{@link DefaultResourceLoader} is a standalone implementation that is + * usable outside an ApplicationContext and is also used by {@link ResourceEditor}. + * + *

Bean properties of type {@code Resource} and {@code Resource[]} can be populated + * from Strings when running in an ApplicationContext, using the particular + * context's resource loading strategy. + * + * @author Juergen Hoeller + * @since 10.03.2004 + * @see Resource + * @see org.springframework.core.io.support.ResourcePatternResolver + * @see org.springframework.context.ApplicationContext + * @see org.springframework.context.ResourceLoaderAware + */ +public interface ResourceLoader { + + /** Pseudo URL prefix for loading from the class path: "classpath:". */ + String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX; + + + /** + * Return a {@code Resource} handle for the specified resource location. + *

The handle should always be a reusable resource descriptor, + * allowing for multiple {@link Resource#getInputStream()} calls. + *

+ *

Note that a {@code Resource} handle does not imply an existing resource; + * you need to invoke {@link Resource#exists} to check for existence. + * @param location the resource location + * @return a corresponding {@code Resource} handle (never {@code null}) + * @see #CLASSPATH_URL_PREFIX + * @see Resource#exists() + * @see Resource#getInputStream() + */ + Resource getResource(String location); //这个是最关键的 + + + /** + * Expose the {@link ClassLoader} used by this {@code ResourceLoader}. + *

Clients which need to access the {@code ClassLoader} directly can do so + * in a uniform manner with the {@code ResourceLoader}, rather than relying + * on the thread context {@code ClassLoader}. + * @return the {@code ClassLoader} + * (only {@code null} if even the system {@code ClassLoader} isn't accessible) + * @see org.springframework.util.ClassUtils#getDefaultClassLoader() + * @see org.springframework.util.ClassUtils#forName(String, ClassLoader) + */ + @Nullable + ClassLoader getClassLoader(); + +} +``` + + + +#### 实现类 + + + + + +1. DefaultResourceLoader:默认资源加载器 + 1. ClassRelativeResourceLoader:能读取类路径相对路径 + 2. FileSystemResourceLoader:能读取文件系统的 + 3. ServletContextResourceLoader:能读取web环境的 + + + + + +### BeanFactory-Bean工厂 + +```java +/** + * The root interface for accessing a Spring bean container. + * 根接口,整个访问容器的入口 + *

This is the basic client view of a bean container; + * further interfaces such as {@link ListableBeanFactory} and + * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory} + * are available for specific purposes. + * + *

This interface is implemented by objects that hold a number of bean definitions, + * 保存很多的BeanDefinition信息,都有一个唯一的名字 + * each uniquely identified by a String name. Depending on the bean definition, + * the factory will return either an independent instance of a contained object + * (the Prototype design pattern【原型模式】), or a single shared instance (a superior + * alternative to the Singleton design pattern【单例设计模式】, in which the instance is a + * singleton in the scope of the factory). Which type of instance will be returned + * depends on the bean factory configuration: the API is the same. Since Spring + * 2.0, further scopes are available depending on the concrete application + * context (e.g. "request" and "session" scopes in a web environment). + * + */ +public interface BeanFactory { + //省略... +} +``` + +> 源码分析小技巧:看源码时,我们可以先看一个类的接口继承关系,因为接口就是规范,大部分开源框架源码都是遵守这一规范的。 + + + + + +1. BeanFactory + 1. HierarchicalBeanFactory:定义父子工厂(父子容器) + 2. ListableBeanFacotory:实现是DefaultListableBeanFactory,保存了ioc容器中的核心信息。 + 3. AutowireCapableBeanFactory:提供自动装配能力 + 4. AnnotationApplicationContext:组合了**一个总的注册中心**(DefaultListableBeanFactory),它有自动装配能力。 + + + + + +#### AbstractApplicationContext + + + +环境类的意思就是谁持有这个策略;这里就解释了上文说ResourceLoader是环境类接口 + +```java + // 策略模式的环境类 + private ResourcePatternResolver resourcePatternResolver; + + public AbstractApplicationContext() { + this.resourcePatternResolver = getResourcePatternResolver(); + } +``` + + + +#### GenericApplicationContext + + + +这里组合了DefaultListableBeanFactory + +```java +public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { + + private final DefaultListableBeanFactory beanFactory; + +} +``` + + + +#### DefaultListableBeanFactory + +```java +public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory + implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { + + + /** Map from serialized id to factory instance. */ + + //组合模式,Spring里面可以有很多工厂,每一个工厂有自己的ID,好处就是工厂之间的bean可以隔离起来,但是用的很少 + private static final Map> serializableFactories = + new ConcurrentHashMap<>(8); + + + /**如果容器中有Map Map of bean definition objects, keyed by bean name. */ + //所有BeanDefinition信息按照名字对应BeanDefinition关系都保存好了。 + private final Map beanDefinitionMap = new ConcurrentHashMap<>(256); + + + /** Map of singleton-only bean names, keyed by dependency type. */ + //Spring中按照类型得到组件的一个底层池 + //车的图纸和车的关系。这里只保存图纸(也就是类信息),对象存哪里呢?往后看 + private final Map, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64); + + /** List of bean definition names, in registration order. */ + //保存所有BeanDefinition的名字。 + private volatile List beanDefinitionNames = new ArrayList<>(256); +``` + + + + + +1. BeanDefinitionRegistry:Bean定义信息注册中心 +2. SimpleAliasRegistry:别名注册中心 +3. SingletonBeanRegistry:单实例注册中心 +4. BeanFactory:Bean工厂 +5. AutowireCapableBeanFactory:有自动装配能力的Bean工厂 +6. DefaultListableBeanFactory:可以理解为拥有上面所有注册中心功能的一个总的注册中心 +7. GenericApplicationContext有一个我们常用的实现类AnnotationConfigApplicationContext,就是注解版的IOC容器 +8. 虽然我们的IOC容器和DefaultListableBeanFactory没有继承的父子关系,但是却组合了DefaultListableBeanFactory,拥有了它的全部功能。 +9. DefaultListableBeanFactory在Spring中扮演着至关重要的角色。 + + + +> 1. DefaultListableBeanFactory保存了所有对象(bean)的图纸(也就是类模板),并没有真正存对象。 +> 2. 我们这里猜想一下,Spring底层真正存Bean的地方用的是哪个数据结构呢?是List,还是Set,还是Map。咱们稍微想一下就知道肯定是Map,并且Key是beanName,value是真正的Bean。如果不是Map的话,如何通过BeanName拿到对应的Bean呢? +> 3. 其实就是上面的那个beanDefinitionMap + + + + + +### 注册BeanDefinition-1 + +- 我们要看BeanDefinition是何时被放入到beanDefinitionMap,只需要在DefaultListableBeanFactory用到`beanDefinitionMap.put()`的地方打个断点。 +- 我们在DefaultListableBeanFactory里搜索,发现了registerBeanDefinition(注册Bean定义信息)这个方法名很像我们要找的东西,再看里面的代码,果然有`beanDefinitionMap.put()`这串代码,我们试着在这里打个断点 +- 然后启动下面的测试类 +- 上面就是我们看一个框架源码,可以往哪些方向去猜测。 + +#### MainTest测试类 + +```java +public class MainTest { + + public static void main(String[] args) throws IOException { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); + Person bean = context.getBean(Person.class); + System.out.println(bean); + + } +} +``` + + + +#### Debug调用栈 + + + +> 调用栈的调用顺序已经非常清楚了,可以把图放大一点看,下面只说一些必要的信息。 + +1. `new ClassPathXmlApplicationContext("beans.xml")`这一步开始就要刷新容器了 + +2. 调用`AbstractApplicationContext#refresh()`这个方法,`refresh()`方法是容器刷新的几大步所在地 + + + +#### AbstractApplicationContext#refresh()容器刷新 + +```java + @Override + public void refresh() throws BeansException, IllegalStateException { + synchronized (this.startupShutdownMonitor) { + StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh"); + + // Prepare this context for refreshing. + prepareRefresh(); + + // Tell the subclass to refresh the internal bean factory. + // BeanFactory第一次开始创建的时候,有xml解析逻辑。 + ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); + + // Prepare the bean factory for use in this context. + prepareBeanFactory(beanFactory); + + try { + // ...... + // Instantiate all remaining (non-lazy-init) singletons. + //完成 BeanFactory 初始化 + finishBeanFactoryInitialization(beanFactory); + + // Last step: publish corresponding event. + finishRefresh(); + } + // ...... + } + } +``` + +#### AbstractApplicationContext#obtainFreshBeanFactory()第一次开始创建BeanFactory + +```java + protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { + refreshBeanFactory(); //刷新整个BeanFactory + return getBeanFactory(); + } +``` + + + +#### AbstractRefreshableApplicationContext#refreshBeanFactory()刷新整个BeanFactory + +```java + protected final void refreshBeanFactory() throws BeansException { + if (hasBeanFactory()) { + destroyBeans(); + closeBeanFactory(); + } + try { + DefaultListableBeanFactory beanFactory = createBeanFactory(); //创建保存所有Bean定义信息的档案馆 + beanFactory.setSerializationId(getId()); + customizeBeanFactory(beanFactory); + loadBeanDefinitions(beanFactory); //开始加载Bean定义信息 + this.beanFactory = beanFactory; + } + catch (IOException ex) { + throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); + } + } +``` + + + +#### AbstractXmlApplicationContext#loadBeanDefinitions()加载Bean定义信息 + +下面就是一堆的loadBeanDefinitions调用,调用顺序就是我下面写的代码顺序。 + +```java + + protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { + // Create a new XmlBeanDefinitionReader for the given BeanFactory. 准备读取xml内容的读取器 + XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); + + // Configure the bean definition reader with this context's + // resource loading environment. + beanDefinitionReader.setEnvironment(this.getEnvironment()); + beanDefinitionReader.setResourceLoader(this); //持有ioc容器的环境类 + beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); + + // Allow a subclass to provide custom initialization of the reader, + // then proceed with actually loading the bean definitions. + initBeanDefinitionReader(beanDefinitionReader); + loadBeanDefinitions(beanDefinitionReader); + } + + protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { + Resource[] configResources = getConfigResources(); + if (configResources != null) { + reader.loadBeanDefinitions(configResources); + } + String[] configLocations = getConfigLocations(); //可以一次传入很多配置文件 + if (configLocations != null) { + reader.loadBeanDefinitions(configLocations); //读取文件 + } + } + +``` + + + +#### AbstractBeanDefinitionReader#loadBeanDefinitions() + +下面也是一堆的loadBeanDefinitions调用,调用顺序就是我下面写的代码顺序。 + +```java + @Override + public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException { + Assert.notNull(locations, "Location array must not be null"); + int count = 0; + for (String location : locations) { //加载每一个配置文件里面的内容 + count += loadBeanDefinitions(location); + } + return count; + } + + @Override //加载指定配置文件的所有内容 + public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException { + return loadBeanDefinitions(location, null); + } + + public int loadBeanDefinitions(String location, @Nullable Set actualResources) throws BeanDefinitionStoreException { + ResourceLoader resourceLoader = getResourceLoader(); + if (resourceLoader == null) { + throw new BeanDefinitionStoreException( + "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available"); + } + + if (resourceLoader instanceof ResourcePatternResolver) { + // Resource pattern matching available. + try { + Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); //得到实体文件对应的资源 + int count = loadBeanDefinitions(resources); + if (actualResources != null) { + Collections.addAll(actualResources, resources); + } + if (logger.isTraceEnabled()) { + logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]"); + } + return count; + } + catch (IOException ex) { + throw new BeanDefinitionStoreException( + "Could not resolve bean definition resource pattern [" + location + "]", ex); + } + } + else { + // Can only load single resources by absolute URL. 这里开始转换成我们前面说的Resource资源 + Resource resource = resourceLoader.getResource(location); + int count = loadBeanDefinitions(resource); + if (actualResources != null) { + actualResources.add(resource); + } + if (logger.isTraceEnabled()) { + logger.trace("Loaded " + count + " bean definitions from location [" + location + "]"); + } + return count; + } + } + + public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException { + Assert.notNull(resources, "Resource array must not be null"); + int count = 0; + for (Resource resource : resources) { + count += loadBeanDefinitions(resource); + } + return count; + } +``` + + + +#### XmlBeanDefinitionReader#loadBeanDefinitions() + +又是一堆loadBeanDefinitions调用 + +```java + @Override + public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { + // 这里是个适配器模式 对接 InputStreamSource 和 Resource 或者说是个装饰器模式也可以 + return loadBeanDefinitions(new EncodedResource(resource)); + } + + + public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { + Assert.notNull(encodedResource, "EncodedResource must not be null"); + if (logger.isTraceEnabled()) { + logger.trace("Loading XML bean definitions from " + encodedResource); + } + + Set currentResources = this.resourcesCurrentlyBeingLoaded.get(); + + if (!currentResources.add(encodedResource)) { + throw new BeanDefinitionStoreException( + "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); + } + + try (InputStream inputStream = encodedResource.getResource().getInputStream()) { + InputSource inputSource = new InputSource(inputStream); + if (encodedResource.getEncoding() != null) { + inputSource.setEncoding(encodedResource.getEncoding()); + } + return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); + } + catch (IOException ex) { + throw new BeanDefinitionStoreException( + "IOException parsing XML document from " + encodedResource.getResource(), ex); + } + finally { + currentResources.remove(encodedResource); + if (currentResources.isEmpty()) { + this.resourcesCurrentlyBeingLoaded.remove(); + } + } + } + + + protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) + throws BeanDefinitionStoreException { + + try { + Document doc = doLoadDocument(inputSource, resource); //利用dom解析工具把xml变成Document + int count = registerBeanDefinitions(doc, resource); //开始注册了 + if (logger.isDebugEnabled()) { + logger.debug("Loaded " + count + " bean definitions from " + resource); + } + return count; + } + catch (BeanDefinitionStoreException ex) { + throw ex; + } + catch (SAXParseException ex) { + throw new XmlBeanDefinitionStoreException(resource.getDescription(), + "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex); + } + catch (SAXException ex) { + throw new XmlBeanDefinitionStoreException(resource.getDescription(), + "XML document from " + resource + " is invalid", ex); + } + catch (ParserConfigurationException ex) { + throw new BeanDefinitionStoreException(resource.getDescription(), + "Parser configuration exception parsing XML from " + resource, ex); + } + catch (IOException ex) { + throw new BeanDefinitionStoreException(resource.getDescription(), + "IOException parsing XML document from " + resource, ex); + } + catch (Throwable ex) { + throw new BeanDefinitionStoreException(resource.getDescription(), + "Unexpected exception parsing XML document from " + resource, ex); + } + } + + + public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { + BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); + int countBefore = getRegistry().getBeanDefinitionCount(); + documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); + return getRegistry().getBeanDefinitionCount() - countBefore; + } +``` + + + +#### DefaultBeanDefinitionDocumentReader#registerBeanDefinitions()注册Bean定义信息 + +```java + @Override + public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { + this.readerContext = readerContext; + doRegisterBeanDefinitions(doc.getDocumentElement()); + } + + protected void doRegisterBeanDefinitions(Element root) { + // this behavior emulates a stack of delegates without actually necessitating one. + BeanDefinitionParserDelegate parent = this.delegate; //由这个类进行最终解析 + this.delegate = createDelegate(getReaderContext(), root, parent); + + //省略不重要的代码...... + preProcessXml(root); + parseBeanDefinitions(root, this.delegate); + postProcessXml(root); + + this.delegate = parent; + } + + + + //省略不重要的代码...... + + + + //最后经过一些列的document文档遍历解析,走到了下面这个方法 + protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { + BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //把当前标签解析完了,BeanDefinition和beanName都封装在了Holder中 + if (bdHolder != null) { + bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); + try { + // Register the final decorated instance. + BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); + } + catch (BeanDefinitionStoreException ex) { + getReaderContext().error("Failed to register bean definition with name '" + + bdHolder.getBeanName() + "'", ele, ex); + } + // Send registration event. //发送一个通知事件 + getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); + } + } +``` + + + + + +#### BeanDefinitionReaderUtils#registerBeanDefinition() + +```java + public static void registerBeanDefinition( + BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) + throws BeanDefinitionStoreException { + + // Register bean definition under primary name. + String beanName = definitionHolder.getBeanName(); + registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); + + // Register aliases for bean name, if any. 别名 + String[] aliases = definitionHolder.getAliases(); + if (aliases != null) { + for (String alias : aliases) { + registry.registerAlias(beanName, alias); + } + } + } +``` + + + +#### DefaultListableBeanFactory#registerBeanDefinition() + +```java + //终于走到了这最后一步 + 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 existingDefinition = this.beanDefinitionMap.get(beanName); + //先看beanDefinitionMap有没有,没有我才注册 + if (existingDefinition != null) { + + //省略一系列目前来说不重要的判断...... + + 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 updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); + updatedDefinitions.addAll(this.beanDefinitionNames); + updatedDefinitions.add(beanName); + this.beanDefinitionNames = updatedDefinitions; + removeManualSingletonName(beanName); + } + } + else { + // Still in startup registration phase + this.beanDefinitionMap.put(beanName, beanDefinition); + this.beanDefinitionNames.add(beanName); + removeManualSingletonName(beanName); + } + this.frozenBeanDefinitionNames = null; + } + + if (existingDefinition != null || containsSingleton(beanName)) { + resetBeanDefinition(beanName); + } + else if (isConfigurationFrozen()) { + clearByTypeCache(); + } + } +``` + + + + + +### 注册BeanDefinition-2 + +#### Debug调用栈 + +- 还有一个debug的猜测方向,想要注册BeanDefinition肯定要new,我们可以直接在AbstractBeanDefinition这个抽象父类的构造函数打断点,我们不知道会走哪个构造函数,所以给三个构造函数都打断点。 +- 下面就是打完断点之后,运行MainTest测试类后的调用栈 + + + + + +> 前面的调用栈都是一样的,从下面开始不一样 + +#### DefaultBeanDefinitionDocumentReader#processBeanDefinition() + +```java + protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { + BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //把当前标签解析完了,BeanDefinition和beanName都封装在了Holder中 + if (bdHolder != null) { + bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); + try { + // Register the final decorated instance. + BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); + } + catch (BeanDefinitionStoreException ex) { + getReaderContext().error("Failed to register bean definition with name '" + + bdHolder.getBeanName() + "'", ele, ex); + } + // Send registration event. //发送一个通知事件 + getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); + } + } +``` + + + +#### BeanDefinitionParserDelegate#parseBeanDefinitionElement() + +```java + public static final String ID_ATTRIBUTE = "id"; + + public static final String NAME_ATTRIBUTE = "name"; + + + public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { + String id = ele.getAttribute(ID_ATTRIBUTE); + String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); + + List aliases = new ArrayList<>(); + if (StringUtils.hasLength(nameAttr)) { + String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); + aliases.addAll(Arrays.asList(nameArr)); + } + + String beanName = id; //为什么说id就是BeanName,Spring源码这里自己写的 + if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { + beanName = aliases.remove(0); + if (logger.isTraceEnabled()) { + logger.trace("No XML 'id' specified - using '" + beanName + + "' as bean name and " + aliases + " as aliases"); + } + } + + if (containingBean == null) { + checkNameUniqueness(beanName, aliases, ele); + } + + AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); + // 省略部分代码...... + String[] aliasesArray = StringUtils.toStringArray(aliases); + return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); + } + + return null; + } + + + public AbstractBeanDefinition parseBeanDefinitionElement( + Element ele, String beanName, @Nullable BeanDefinition containingBean) { + + this.parseState.push(new BeanEntry(beanName)); + + String className = null; + if (ele.hasAttribute(CLASS_ATTRIBUTE)) { + className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); + } + String parent = null; + if (ele.hasAttribute(PARENT_ATTRIBUTE)) { + parent = ele.getAttribute(PARENT_ATTRIBUTE); + } + + try { + AbstractBeanDefinition bd = createBeanDefinition(className, parent); + + parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); + bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); + //以下是解析Bean标签里面的元数据填充完 BeanDefinition + parseMetaElements(ele, bd); + parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); + parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); + + parseConstructorArgElements(ele, bd); + parsePropertyElements(ele, bd); + parseQualifierElements(ele, bd); + + bd.setResource(this.readerContext.getResource()); + bd.setSource(extractSource(ele)); + + return bd; + } + catch (ClassNotFoundException ex) { + error("Bean class [" + className + "] not found", ele, ex); //这个就是我们常见的错误 + } + catch (NoClassDefFoundError err) { + error("Class that bean class [" + className + "] depends on not found", ele, err); + } + catch (Throwable ex) { + error("Unexpected failure during bean definition parsing", ele, ex); + } + finally { + this.parseState.pop(); + } + + return null; + } + + + protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName) + throws ClassNotFoundException { + + return BeanDefinitionReaderUtils.createBeanDefinition( + parentName, className, this.readerContext.getBeanClassLoader()); + } +``` + + + +#### BeanDefinitionReaderUtils#createBeanDefinition() + +```java + public static AbstractBeanDefinition createBeanDefinition( + @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException { + + GenericBeanDefinition bd = new GenericBeanDefinition(); //创建了一个BeanDefintion准备封装标签的内容 + bd.setParentName(parentName); + if (className != null) { + if (classLoader != null) { + bd.setBeanClass(ClassUtils.forName(className, classLoader)); + } + else { + bd.setBeanClassName(className); + } + } + return bd; + } +``` + +> 至此结束,上面的都不是很难,顺着调用栈就能看懂。 + + + +### ApplicationContext接口功能 + + + +1. ioc事件派发器 +2. 国际化解析 +3. bean工厂功能---自动装配被组合进来的 +4. 资源解析功能 +5. 等等 + +> 这个就是我们常说的IOC容器 + + + +### Aware接口功能分析 + +1. aware中文翻译是**意识到的,察觉到的,发现**这么个意思。从翻译来看,aware做的事情应该是发现某一个东西。 + +```java +/** + * Marker superinterface indicating that a bean is eligible to be + * notified by the Spring container of a particular framework object + * through a callback-style method. Actual method signature is + * determined by individual subinterfaces, but should typically + * consist of just one void-returning method that accepts a single + * argument. + */ +public interface Aware { + +} +``` + +2. 注释的大致意思是:Aware是一个标记性的超接口(顶级接口),指示了一个Bean有资格通过回调方法的形式获取Spring容器底层组件。实际回调方法被定义在每一个子接口中,而且通常一个子接口只包含一个接口一个参数并且返回值为void的方法。 +3. 说白了:只要实现了Aware子接口的Bean都能获取到一个Spring底层组件。 + + + +比如实现了ApplicationContextAware接口,实现它的方法,就能通过回调机制拿到ApplicationContext + + + +#### 创建Person对象 + +##### Debug调用栈 + +为了知道Aware的原理,我们给上面的pos_1和pos_2位置打上断点,看下是怎么进来的 + +**Person** + +```java +@Component +public class Person implements ApplicationContextAware, MessageSourceAware { + + ApplicationContext context; //我们不用@Autowired也可以要到ioc容器 + MessageSource messageSource; + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public Person(){ + System.out.println("person创建...."); //pos_1 + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + //利用回调机制,把ioc容器传入 + this.context = applicationContext; //pos_2 + } + + @Override + public void setMessageSource(MessageSource messageSource) { + this.messageSource = messageSource; + } +} +``` + +**AnnotationMainTest** + +```java +/** + * 注解版Spring的用法 + */ +public class AnnotationMainTest { + + public static void main(String[] args) { + ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); + Person bean = applicationContext.getBean(Person.class); + ApplicationContext context = bean.getContext(); + + System.out.println(context == applicationContext); + } +``` + +**MainConfig** + +```java +@ComponentScan("cn.imlql.spring") +@Configuration +public class MainConfig { + + public Person person(){ + Person person = new Person(); + person.setName("李四"); + return person; + } +} +``` + + + + + + + +1. 有一些一样的东西不再赘述 +2. 在`AbstractApplicationContext#refresh()`里会调用 + +##### AbstractApplicationContext#finishBeanFactoryInitialization()完成 BeanFactory 初始化 + + + +```java + @Override + public void refresh() throws BeansException, IllegalStateException { + synchronized (this.startupShutdownMonitor) { + StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh"); + + // BeanFactory第一次开始创建的时候,有xml解析逻辑。 + ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); + // ... + try { + // Instantiate all remaining (non-lazy-init) singletons. + //完成 BeanFactory 初始化 + finishBeanFactoryInitialization(beanFactory); + } + } + } + + protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { + // Instantiate all remaining (non-lazy-init) singletons. + //初始化所有的单实例Bean + beanFactory.preInstantiateSingletons(); + } +``` + +##### DefaultListableBeanFactory#preInstantiateSingletons()循环遍历beanDefinitionName + +```java + @Override + public void preInstantiateSingletons() throws BeansException { + if (logger.isTraceEnabled()) { + logger.trace("Pre-instantiating singletons in " + this); + } + + List beanNames = new ArrayList<>(this.beanDefinitionNames); + + // Trigger initialization of all non-lazy singleton beans... + for (String beanName : beanNames) {//挨个遍历beanDefinitionName + RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); + if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { + if (isFactoryBean(beanName)) { + // ... + } + else { + getBean(beanName); + } + } + } + + } +``` + +##### AbstractBeanFactory#getBean()准备获取Bean + +```java + @Override + public Object getBean(String name) throws BeansException { + return doGetBean(name, null, null, false); + } + + protected T doGetBean( + String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) + throws BeansException { + + String beanName = transformedBeanName(name); //转换Bean名字 + Object beanInstance; + + // Eagerly check singleton cache for manually registered singletons. + Object sharedInstance = getSingleton(beanName); //检查缓存中有没有 + if (sharedInstance != null && args == null) { + //... + } + + else { + //... + try { + String[] dependsOn = mbd.getDependsOn(); + if (dependsOn != null) { + for (String dep : dependsOn) { //看当前Bean有没有依赖其他Bean + + try { + getBean(dep); //依赖了其他bean,就先获取其他的哪些bean + } + //... + } + } + + // Create bean instance. 创建bean的实例,下面是一个lamda表达式 + if (mbd.isSingleton()) { + sharedInstance = getSingleton(beanName, () -> { + try { + return createBean(beanName, mbd, args); //创建bean对象的实例 + } + }); + beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); + } + } + + return adaptBeanInstance(name, beanInstance, requiredType); + } +``` + +##### DefaultSingletonBeanRegistry#getSingleton() + +```java + public Object getSingleton(String beanName, ObjectFactory singletonFactory) { + Assert.notNull(beanName, "Bean name must not be null"); + synchronized (this.singletonObjects) { + // ... + try { + // 通过getObject获取真正的对象,有点类似于FactoryBean(这个不懂的建议先了解下Spring基本欧诺个发), + // ObjectFactory类注释有说明。 + singletonObject = singletonFactory.getObject(); + newSingleton = true; + // ... + } + + return singletonObject; + } + } +``` + +下面就开始分析lamda表达式里的东西 + +##### AbstractAutowireCapableBeanFactory#createBean() + +```java + protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) + throws BeanCreationException { + //... + try { + Object beanInstance = doCreateBean(beanName, mbdToUse, args); + if (logger.isTraceEnabled()) { + logger.trace("Finished creating instance of bean '" + beanName + "'"); + } + return beanInstance; + } + } + + protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) + throws BeanCreationException { + //... + if (instanceWrapper == null) { + //创建Bean的实例,默认使用无参构造器创建的对象 + instanceWrapper = createBeanInstance(beanName, mbd, args); + } + } + + protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { + //... + return instantiateBean(beanName, mbd); + } + + /** 指定Bean的创建策略;可以用jdk的反射,可以用cglib创建子类对象 Strategy for creating bean instances. */ + private InstantiationStrategy instantiationStrategy; + protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) { + try { + Object beanInstance; + else { + beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this); + } + BeanWrapper bw = new BeanWrapperImpl(beanInstance); + initBeanWrapper(bw); + return bw; + } + } +``` + +##### SimpleInstantiationStrategy#instantiate()反射创建Bean + +```java + public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { + // Don't override the class with CGLIB if no overrides. + if (!bd.hasMethodOverrides()) { + return BeanUtils.instantiateClass(constructorToUse); + } + } + +``` + +##### Spring内部的BeanUtils反射工具 + +> 这个类是Spring内部提供的反射工具类,平时项目你也可以用上,就不用自己写反射了 + +```java + public static T instantiateClass(Constructor ctor, Object... args) throws BeanInstantiationException { + Assert.notNull(ctor, "Constructor must not be null"); + try { + ReflectionUtils.makeAccessible(ctor); + else { + Object[] argsWithDefaultValues = new Object[args.length]; + return ctor.newInstance(argsWithDefaultValues); + } + } + } + // 后面就是反射创建Person +``` + + + +#### Aware回调原理 + +##### Debug调用栈 + + + + + +前面有很多一样的调用链,不再赘述。从doCreateBean:602调用栈开始不一样 + +##### AbstractAutowireCapableBeanFactory#doCreateBean() + +```java + protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) + throws BeanCreationException { + + // Initialize the bean instance. + Object exposedObject = bean; + try { + populateBean(beanName, mbd, instanceWrapper); + exposedObject = initializeBean(beanName, exposedObject, mbd); + } + } + + + protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { + Object wrappedBean = bean; + if (mbd == null || !mbd.isSynthetic()) { + wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); + } + return wrappedBean; + } + + + public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) + throws BeansException { + + Object result = existingBean; + for (BeanPostProcessor processor : getBeanPostProcessors()) { + Object current = processor.postProcessBeforeInitialization(result, beanName); + if (current == null) { + return result; + } + result = current; + } + return result; + } +``` + +##### ApplicationContextAwareProcessor + +```java + @Override + @Nullable + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || + bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || + bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware || + bean instanceof ApplicationStartupAware)) { + return bean; + } + //... + else { + invokeAwareInterfaces(bean); //执行aware接口规定的方法 + } + + return bean; + } + + //就是在这里执行Aware回调 + private void invokeAwareInterfaces(Object bean) { + if (bean instanceof EnvironmentAware) { + ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); + } + if (bean instanceof EmbeddedValueResolverAware) { + ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); + } + if (bean instanceof ResourceLoaderAware) { + ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); + } + if (bean instanceof ApplicationEventPublisherAware) { + ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); + } + if (bean instanceof MessageSourceAware) { + ((MessageSourceAware) bean).setMessageSource(this.applicationContext); + } + if (bean instanceof ApplicationStartupAware) { + ((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup()); + } + if (bean instanceof ApplicationContextAware) { + ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); + } + } +``` + + + + + +## 属性赋值的时机(XML版) + +### Debug调用栈 + +**Person** + +```java +public class Person implements ApplicationContextAware, MessageSourceAware { + + ApplicationContext context; //我们不用@Autowired也可以要到ioc容器 + MessageSource messageSource; + + public void setName(String name) { + this.name = name; // pos_2 + } + + public String getName() { + return name; + } + + public Person(){ + System.out.println("person创建...."); //pos_1 + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + //利用回调机制,把ioc容器传入 + this.context = applicationContext; + } + + @Override + public void setMessageSource(MessageSource messageSource) { + this.messageSource = messageSource; + } +} +``` + +**MainTest** + +```java +public class MainTest { + + public static void main(String[] args) { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); + Person bean = context.getBean(Person.class); + System.out.println(bean); + } + +} +``` + +**beans.xml** + +```xml + + + + + + + + +``` + + + +为了知道属性赋值的时机,这里要给setXXX方法打断点,也就是上面的pos_1和pos_2位置打断点。 + + + + + + + +还是老规矩,一样的就不说了,从调用栈不一样的地方开始说起。多看几遍,看到后面就会发现思路越来越清晰了。 + + + +### AbstractAutowireCapableBeanFactory#doCreateBean() + + + +```java + protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) + throws BeanCreationException { + + // Instantiate the bean. 这里面封装好了真正的Person对象 + BeanWrapper instanceWrapper = null; + if (mbd.isSingleton()) { + instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); + } + if (instanceWrapper == null) { + //创建Bean的实例,默认使用无参构造器创建的对象 + instanceWrapper = createBeanInstance(beanName, mbd, args); + } + + //...... + + // Initialize the bean instance. + Object exposedObject = bean; + try { + populateBean(beanName, mbd, instanceWrapper); //给创建好的对象每个属性进行赋值 + exposedObject = initializeBean(beanName, exposedObject, mbd);//初始化bean + } + return exposedObject; + } + +``` + +我们看到此时,Person的name属性还是null + + + + + +### AbstractAutowireCapableBeanFactory#populateBean()属性赋值 + +```java + protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { + // 这一步就是拿到属性值 + PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); + + // ...... + + if (pvs != null) { + applyPropertyValues(beanName, mbd, bw, pvs); //xml版的所有配置会来到这里给属性赋值 + } + } + +``` + +这里拿到属性值 + + + + + +```java + protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { + // ...... + + // Set our (possibly massaged) deep copy. + try { //深拷贝所有PropertyValue应该对应的属性 + bw.setPropertyValues(new MutablePropertyValues(deepCopy)); + } + } +``` + + + + + +bw就是上面说的 => 里面封装好了真正的Person对象 + + + + + + + + + +这里就是一层一层调,不重要跳过。 + + + + + +### AbstractNestablePropertyAccessor#processLocalProperty + +```java +private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) { + // ... + try { + Object originalValue = pv.getValue(); + Object valueToApply = originalValue; + ph.setValue(valueToApply); + } + //... + } + +``` + + + + + + + + + +### BeanWrapperImpl内部类BeanPropertyHandler#setValue() + +```java +private class BeanPropertyHandler extends PropertyHandler { + @Override + public void setValue(@Nullable Object value) throws Exception { + Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ? + ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() : + this.pd.getWriteMethod()); + if (System.getSecurityManager() != null) { + AccessController.doPrivileged((PrivilegedAction) () -> { + ReflectionUtils.makeAccessible(writeMethod); + return null; + }); + try { + AccessController.doPrivileged((PrivilegedExceptionAction) + () -> writeMethod.invoke(getWrappedInstance(), value), acc); + } + catch (PrivilegedActionException ex) { + throw ex.getException(); + } + } + else { + ReflectionUtils.makeAccessible(writeMethod); + // 这里的意思就是找到这个属性的写方法,所谓写方法就是setxxx方法 + writeMethod.invoke(getWrappedInstance(), value); + } + } +} +``` + + + + + +最后就是反射走到了我们的`Person#setName(String name)` + + + + + +### 再来看看messageSource何时赋值 + + + + + +剩下的在上面的Aware回调原理讲过 + + + + + +## 属性赋值的时机(注解版) + +### Debug调用栈 + + + +**AnnotationMainTest** + +```java +public class AnnotationMainTest { + public static void main(String[] args) { + + ApplicationContext applicationContext = + new AnnotationConfigApplicationContext(MainConfig.class); + + Person bean = applicationContext.getBean(Person.class); + ApplicationContext context = bean.getContext(); + System.out.println(context == applicationContext); + } +} +``` + +**Cat** + +```java +@Component +public class Cat { + + public Cat(){ + System.out.println("cat被创建了..."); + } + + private String name; + + + @Value("${JAVA_HOME}") //自动赋值功能 + public void setName(String name) { + System.out.println("cat....setName正在赋值调用...."); + this.name = name; + } + + public String getName() { + return name; + } +} +``` + +**MainConfig** + +```java +@ComponentScan("cn.imlql.spring") +@Configuration +public class MainConfig { + + public MainConfig(){ + System.out.println("MainConfig...创建了...."); + } + + public Person person(){ + Person person = new Person(); + person.setName("李四"); + return person; + } +} +``` + +**Person** + +```java +@Component +public class Person implements ApplicationContextAware, MessageSourceAware { + + ApplicationContext context; //可以要到ioc容器 + + MessageSource messageSource; + + private String name; + + private Cat cat; + + + public Person(){ + System.out.println("person创建...."); + } + + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + + + @Autowired //去发现一下..... + public void setCat(Cat cat) { + this.cat = cat; + } + + public Cat getCat() { + return cat; + } + + @Override + public String toString() { + return "Person{" + + "name='" + name + '\'' + + '}'; + } + + + public ApplicationContext getContext() { + return context; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + //利用回调机制,把ioc容器传入 + this.context = applicationContext; + } + + @Override + public void setMessageSource(MessageSource messageSource) { + this.messageSource = messageSource; + } +} +``` + + + +老样子,只看不一样的调用栈 + + + +### AbstractAutowireCapableBeanFactory#populateBean() + +```java + protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { + + // ...... + PropertyDescriptor[] filteredPds = null; + if (hasInstAwareBpps) { + if (pvs == null) { + pvs = mbd.getPropertyValues(); + } + for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { + // 注解版的属性赋值会走这里 + PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); + if (pvsToUse == null) { + if (filteredPds == null) { + filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); + } + pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); + if (pvsToUse == null) { + return; + } + } + pvs = pvsToUse; + } + } + if (needsDepCheck) { + if (filteredPds == null) { + filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); + } + checkDependencies(beanName, mbd, filteredPds, pvs); + } + + if (pvs != null) { + applyPropertyValues(beanName, mbd, bw, pvs); //xml版的所有配置会来到这里给属性赋值 + } + } +``` + +这里有一个非常著名的后置处理器,`AutowiredAnnotationBeanPostProcessor`自动装配注解后置处理器,顾名思义就是用来处理@Autowired注解自动装配的。 + + + + + + + +### AutowiredAnnotationBeanPostProcessor#postProcessProperties() + +```java + public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { + 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; + } +``` + + + + + +> 下面的代码不在debug调用栈里,但是也比较重要 + + + +```java + private InjectionMetadata findAutowiringMetadata(String beanName, Class clazz, @Nullable PropertyValues pvs) { + // Fall back to class name as cache key, for backwards compatibility with custom callers. + String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); + // Quick check on the concurrent map first, with minimal locking. + InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); + if (InjectionMetadata.needsRefresh(metadata, clazz)) { + synchronized (this.injectionMetadataCache) { + metadata = this.injectionMetadataCache.get(cacheKey); + if (InjectionMetadata.needsRefresh(metadata, clazz)) { + if (metadata != null) { + metadata.clear(pvs); + }//下面是分析当前类方法或者属性有没有标注@Autowired等自动赋值的注解 + metadata = buildAutowiringMetadata(clazz); + this.injectionMetadataCache.put(cacheKey, metadata); + } + } + } + return metadata; + } + + private InjectionMetadata buildAutowiringMetadata(final Class clazz) { + if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { + return InjectionMetadata.EMPTY; + } + + List elements = new ArrayList<>(); + Class targetClass = clazz; + + do { + final List currElements = new ArrayList<>(); + //找所有属性中标注了@Autowired\@Value\@Inject注解 + ReflectionUtils.doWithLocalFields(targetClass, field -> { + MergedAnnotation ann = findAutowiredAnnotation(field); + if (ann != null) { + if (Modifier.isStatic(field.getModifiers())) { + if (logger.isInfoEnabled()) { + logger.info("Autowired annotation is not supported on static fields: " + field); + } + return; + } + boolean required = determineRequiredStatus(ann); + currElements.add(new AutowiredFieldElement(field, required)); + } + }); + //拿到所有方法,看有没有@Autowired注解 + ReflectionUtils.doWithLocalMethods(targetClass, method -> { + Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); + if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { + return; + } + MergedAnnotation ann = findAutowiredAnnotation(bridgedMethod); + if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { + if (Modifier.isStatic(method.getModifiers())) { + if (logger.isInfoEnabled()) { + logger.info("Autowired annotation is not supported on static methods: " + method); + } + return; + } + if (method.getParameterCount() == 0) { + if (logger.isInfoEnabled()) { + logger.info("Autowired annotation should only be used on methods with parameters: " + + method); + } + } + boolean required = determineRequiredStatus(ann); + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); + currElements.add(new AutowiredMethodElement(method, required, pd)); + } + }); + + elements.addAll(0, currElements); + targetClass = targetClass.getSuperclass(); + } + while (targetClass != null && targetClass != Object.class); + + return InjectionMetadata.forElements(elements, clazz); + } +``` + +> BeanUtils:Bean反射工具类 +> +> ReflectionUtils:真正操作反射的工具类 + +```java + @Nullable + private MergedAnnotation findAutowiredAnnotation(AccessibleObject ao) { + MergedAnnotations annotations = MergedAnnotations.from(ao); + for (Class type : this.autowiredAnnotationTypes) { + MergedAnnotation annotation = annotations.get(type); + if (annotation.isPresent()) { + return annotation; + } + } + return null; + } + + private final Set> autowiredAnnotationTypes = new LinkedHashSet<>(4); + + public AutowiredAnnotationBeanPostProcessor() { + this.autowiredAnnotationTypes.add(Autowired.class); + this.autowiredAnnotationTypes.add(Value.class); + try { + this.autowiredAnnotationTypes.add((Class) + ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader())); + logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring"); + } + catch (ClassNotFoundException ex) { + // JSR-330 API not available - simply skip. + } + } +``` + + + +### InjectionMetadata#inject() + +```java + public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { + Collection checkedElements = this.checkedElements; + Collection elementsToIterate = + (checkedElements != null ? checkedElements : this.injectedElements); + if (!elementsToIterate.isEmpty()) { + for (InjectedElement element : elementsToIterate) { + element.inject(target, beanName, pvs); + } + } + } +``` + + + +### AutowiredAnnotationBeanPostProcessor内部类AutowiredMethodElement#inject() + +```java + protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { + if (checkPropertySkipping(pvs)) { + return; + } + Method method = (Method) this.member; + Object[] arguments; + if (this.cached) { + try { + arguments = resolveCachedArguments(beanName); + } + catch (NoSuchBeanDefinitionException ex) { + // Unexpected removal of target bean for cached argument -> re-resolve + arguments = resolveMethodArguments(method, bean, beanName); + } + } + else { + arguments = resolveMethodArguments(method, bean, beanName); + } + if (arguments != null) { + try { + ReflectionUtils.makeAccessible(method); + method.invoke(bean, arguments);// 这里就是反射调用setXXX了 + } + catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } + } + } +``` + +BeanPostProcessor后置处理器贯穿整个Spring框架,Spring的事务,属性赋值,等等各方面都与其有着密不可分的关系,后面就开始讲BeanPostProcessor + + +