Spring @Autowired注解解析

标签: spring  spring  java  ioc

前言

在我们学习 spring 的时候,尤其是使用注解的方式实现自动装配,总会感到很神奇,也产生了很多的疑问。

  • 注解是什么时候被解析的?
  • 注解的生效逻辑是什么?

以@Autowired 为例,为什么加了这个直接就可以直接得到对应的属性实例,并调用它的方法呢?

我们越学感觉到疑问越多,而光看源码又容易被带偏,总是一个问题深入研究下去就找不到回来的路了。

本文试着从问题的角度出发,边看源码边解答这些疑问,这样思路清晰一些。

阅读本文时,我假定阅读者已经粗略的看过 springioc 和 springaop 相关的源码,有一定的基础,所以可能非关键步骤会略过。

解答

下面跟着一起来看看吧,大家打开自己的源码工程跟着一起做。

我们知道 spring 的启动配置有 3 中方式:xml 的方式、注解的方式、java 配置方式,其实主要分析 xml 和注解方式就可以了,他们在解析注解有一定的差异,我们分开分析。

我们主要分析 xml 方式和注解方式启动,解答之前我们先构建一下项目代码:

XML 配置文件的方式启动服务

注解是什么时候被解析的

测试启动类

public class MainStart {
    
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans/beans2.xml");
    }
}

定义几个 bean

// 使用注解方式注入
@Service(value = "ioc2")
public class IOCService2Impl implements IOCService {
	
	@Autowired
	@Qualifier(value = "iocService")
	private IOCService iocService;
	
	@Override
	public String hollo() {
		return "Hello,IOC";
	}
}
// 使用配置文件的方式注入
public class IOCServiceImpl implements IOCService {
    
    @Override
    public String hollo() {
        return "Hello,IOC";
    }
}
// 接口
public interface IOCService {
    public String hollo();
}

配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/tool"
		xmlns:context="http://www.springframework.org/schema/context"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"
		default-autowire="byName">
    <!-- 手动注入bean -->
	<bean class="top.ybq.ioc.beanlifecycle.xml2.IOCServiceImpl" id="iocService"/>
    <!-- 开启扫包自动注入 -->
	<context:component-scan base-package="top.ybq.ioc.beanlifecycle.xml2"/>
</beans>

我们在 org.springframework.context.support.AbstractApplicationContext#refresh 这个方法打个断点然后启动

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

image-20200426155755286

image-20200426155955985

我们看到第一张图 BeanFactory 是 null ,然后我们跳到下一步看第二张图,这里又有值了,说明 spring 在 xml 配置方式启动的时候,会在这个方法里去解析所有的注解。

obtainFreshBeanFactory()做了什么?

我们跟踪到了 AbstractRefreshableApplicationContext#refreshBeanFactory

@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        // 关闭工厂
        closeBeanFactory();
    }
    try {
        /**
		 * 创建 DefaultListableBeanFactory 类型的 BeanFactory,目前还没有任何属性
		 * 这个类超级强大,所有关于容器的接口、抽象类它都继承了
		 */
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        /**
		 * 为容器设置一个序列化 id
		 */
        beanFactory.setSerializationId(getId());
        /**
		 * 设置 BeanFactory的2个配置属性, 是否允许bean覆盖,是否允许循环引用
		 */
        customizeBeanFactory(beanFactory);
        /**
		 * 加载我们的 bean 定义(最最最主要的作用就是保存我们的传递进去的配置类)
		 * 此方法是一个抽象方法,需要交给子类去实现,用于加载自定义的 BeanDefinition
		 * 其中 4 个子类:
		 * FileSystemXmlApplicationContext: 从文件系统加载配置类
		 * ClassPathXmlApplicationContext: 从 classpath 加载配置文件,子类 AbstractXmlApplicationContext 实现了此方法,一般用 xml 配置启动的,看这个类的实现
		 * AnnotationConfigWebApplicationContext: 以注解的方式加载配置的bean
		 * XmlWebApplictaionContext:
		 */
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

看我的注释其他的方法大致做什么就知道了,我们去看AbstractXmlApplicationContext#loadBeanDefinitions方法,跟进到XmlBeanDefinitionReader#loadBeanDefinitions,然后XmlBeanDefinitionReader#doLoadBeanDefinitions

spring 框架中真正干活的方法都是 do、parse 等开头的,所以看到这几个前缀就知道它要干活了。

// 摘取部分代码
try {
    // 使用 document 的方式读取配置文件信息
    Document doc = doLoadDocument(inputSource, resource);
    /**
	 * 依据 document 信息解析 bean,注册 BeanDefinition,关键位置
	 */
    int count = registerBeanDefinitions(doc, resource);
    if (logger.isDebugEnabled()) {
        logger.debug("Loaded " + count + " bean definitions from " + resource);
    }
    return count;
}

跟进之后

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    // 构建读取 document 的工具类
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    // 获取已经注册的 bean 的数量
    int countBefore = getRegistry().getBeanDefinitionCount();
    /**
	 * 注册BeanDefinition, 看 registerBeanDefinitions() 方法
	 */
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // 总注册 bean 数量减去之前注册的数量,就是本次注册的 bean 数量
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

再次看到了 do 方法DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions

这个方法的第一部分的作用是:获取 <beans … profile="***" /> 中的 profile参数与当前环境是否匹配,如果不匹配则不再进行解析。

这个和环境变量相关,我们先不讨论,看后面的DefaultBeanDefinitionDocumentReader#parseBeanDefinitions方法。

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    /**
	 * 判定是否是默认节点,spring 默认的标签有且只有 4 个:<import/>、<alias>、<bean>、<beans>
	 * spring 只有 4 个默认标签,其他的标签都属于自定义标签,
	 * 比如:<tx:annotation-driven/>、注解扫描标签<context:component-scan/>,对应的是 注解 @Component @trans...
	 * 这些都是自定义节点
	 */
    if (delegate.isDefaultNamespace(root)) {
        // 默认标签解析
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    /**
					 * 默认标签处理,我们不展开,留给读者自己去跟踪,如果按照demo 中的代码,这里就是解析 <bean> 节点
					 */
                    parseDefaultElement(ele, delegate);
                }
                else {
                    /**
					 * 自定义标签的解析, 这是我们重点分析的
					 */
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        // 自定义标签解析
        delegate.parseCustomElement(root);
    }
}

老铁们,好像跟到这里有点苗头了,我们看到了和标签相关的说明。

good

跟进到这里,parse 开头的方法就是真正干活的苦力。

默认标签不是我们分析的重点,大家参考自定义标签的分析再去看看就好了,我们这里分析的是注解什么时候解析的,所以我们只关注自定义标签。

来,继续看自定义标签的解析

public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
    // 获取命名空间,
    String namespaceUri = getNamespaceURI(ele);
    if (namespaceUri == null) {
        return null;
    }
    // 通过 namespace 获取到 NamespaceHandler,重点看 resolve() 方法
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    }
    // 进行解析
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

我们调试到这里断点发现

image-20200426162226931

这个就是来处理我们自定义标签<context:component-scan base-package="top.ybq.ioc.beanlifecycle.xml2"/>,同时我们得到了一个叫做命名空间的串:"http://www.springframework.org/schema/context”和我们在 xml 文件中配置的xmlns:context="http://www.springframework.org/schema/context”关联起来的。

那么这个 namespaceUri 有什么作用呢,我们跟着注释去看看 reslove 方法DefaultNamespaceHandlerResolver#resolve

public NamespaceHandler resolve(String namespaceUri) {
    /**
	 * 获取所有一级配置的 handler ,getHandlerMappings():方法获取到所有命名空间对应的 uri,
	 * 比如 beans.xml 文件中配置包扫描的时候用到的自定义标签<context:component-scan xx>
	 *     它的对应的 uri = http://www.springframework.org/schema/context,
	 *
	 * 研究方法发现其实是去读取配置文件 META-INF/spring.handlers 然后获取到 namespaceUri 对应的 class 的全限定类名
	 *
	 * 另外:
	 * getHandlerMappings()方法有个小坑,我们正常debug进入时发现handlerMappings已经被初始化了,但是我们没有找到任何地方调用它的,除了一个 toString()方法,所以就是因为这个toString的问题导致handlerMappings提前初始化【debug 查看这个属性其实调用了 toString() 方法】。
	 * 具体参考: https://www.zhihu.com/question/61890921
	 */
    Map<String, Object> handlerMappings = getHandlerMappings();
    /**
	 * 通过 uri 得到对应的 ClassName,org.springframework.context.config.ContextNamespaceHandler
	 */
    Object handlerOrClassName = handlerMappings.get(namespaceUri);
    if (handlerOrClassName == null) {
        return null;
    }
    else if (handlerOrClassName instanceof NamespaceHandler) {
        return (NamespaceHandler) handlerOrClassName;
    }
    else {
        String className = (String) handlerOrClassName;
        try {
            // 得到了 className 之后,就可以利用反射创建这个类了。
            Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
            if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
                throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
                                             "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
            }
            // 实例化对象
            NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
            /**
			 * 调用该对象的 init 方法,我们以自定标签 <context:component-scan xx> 为例,她得到的 className = org.springframework.context.config.ContextNamespaceHandler
			 * 我们查看这个类的实现,发现其中有一个 init 方法,
			 * 找到了:registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
			 * 这里只是实例化了这个方法,并且加入了这个 parser,但是并没有开始调用。
			 * 那么什么时候调用的 parse 呢?我们看回上一步 BeanDefinitionParserDelegate.parseCustomElement 方法,最后一步,
			 * handler.parse(ele, new ParserContext(this.readerContext, this, containingBd))
			 * 调用 NamespaceHandlerSupport.parse
			 */
            namespaceHandler.init();
            // 将对象放入缓存
            handlerMappings.put(namespaceUri, namespaceHandler);
            return namespaceHandler;
        }
        catch (ClassNotFoundException ex) {
            throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
                                         "] for namespace [" + namespaceUri + "]", ex);
        }
        catch (LinkageError err) {
            throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
                                         className + "] for namespace [" + namespaceUri + "]", err);
        }
    }
}

喘口气,我们看了这么多,终于在这里看到了可能是我们想要的方法ComponentScanBeanDefinitionParser#parse,这里应该是去解析注解了吧。

public BeanDefinition parse(Element element, ParserContext parserContext) {
    String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
    basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
    String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
                                                              ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

    // Actually scan for bean definitions and register them.
    /**
	 * 定义一个扫描器,用来扫包,这个方法主要是创建了 ClassPathBeanDefinitionScanner 实例,
	 * 然后在它的构造方法中调用了 registerDefaultFilters(); 方法,这个方法是为 this.includeFilters 属性赋值
	 * 将 @Component 注解加入进入,在后面我们扫包时,加载了所有的 class 文件,在判断是否需要解析为 BeanDefinition 从而注册到 BeanFactory 时
	 * 会有判定是否在 this.includeFilters 包含了这个 class。看到后面大家会明白
	 */
    ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
    /**
	 * 开始扫描,扫到的 bean 的定义信息 BeanDefinition
	 * 扫描的是指定包下的所有 class 文件,使用 asm 技术,将符合规则的 bean 转为 BeanDefinition。
	 * 一些通过注解注册的属性,比如 @Primary、@Description、@Role、@Lazy、@DependsOn 等解析,属性设置到 BeanDefinition 中
	 */
    Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
    // 注册注解解析类,重点
    registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

    return null;
}

这里有 2 个值得看的方法,一个是 doScan 一个是后面的 registerComponents方法

doScan

我们跟进到 ClassPathBeanDefinitionScanner#doScan 看看

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    // 循环包
    for (String basePackage : basePackages) {
        /**
		 * 此方法扫到所有自动注入的 BeanDefinition,
		 * 大致的流程如下:
		 * 1、先根据 context:component-scan 中属性的 base-package="top.ybq87.xx" 配置转换为 classpath*:top/ybq87/ybq87/**\/*.class(默认格式),
		 * 并扫描对应下的class和jar文件并获取类对应的路径,返回Resources。
		 * 2、根据指定的不扫描包,指定的扫描包配置进行过滤不包含的包对应下的class和jar。
		 * 3、封装成BeanDefinition放到队列里。
		 * 实际上,是把所有包下的 class 文件都扫描了的,并且利用 asm 技术读取 java 字节码并转化为 MetadataReader 中的 AnnotationMetadataReadingVisitor 结构
		 */
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            // 获取@Scope注解的值,即获取Bean的作用域
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            // 为Bean设置作用域
            candidate.setScope(scopeMetadata.getScopeName());
            // 查看是否配置类是否指定 bean 的名称,没有指定则使用类名首字母小写
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

            /**
			 * 下面两个if是处理 lazy、AutowireMode、DependencyOn、initMethod、enforceInitMethod、
			 * destroyMethod、enforceDestroyMethod、Primary、Role、Description 这些逻辑的
			 */
            if (candidate instanceof AbstractBeanDefinition) {
                /**
				 * 主要工作,重点是设置自动装配类型,AutowiredMode
				 */
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            // 注解 @Primary、@Role、@Lazy、@DependsOn、@Description 等解析,属性设置到 BeanDefinition 中
            if (candidate instanceof AnnotatedBeanDefinition) {
                // 配置通过注解设置的属性,设置到 BeanDefinition 中
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            // 根据 Bean 名称检查指定的 Bean 是否需要在容器中注册,或者在容器中冲突
            if (checkCandidate(beanName, candidate)) {
                // 包装
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                // 根据注解中配置的作用域,为 Bean 应用相应的代理模式
                definitionHolder =
                    AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                /**
				 * 把我们解析出来的组件bean定义注册到我们的IOC容器中
				 */
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

我们跟进到findCandidateComponents,找到方法ClassPathScanningCandidateComponentProvider#scanCandidateComponents

if (isCandidateComponent(metadataReader)) {
    ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
    sbd.setResource(resource);
    sbd.setSource(resource);
    if (isCandidateComponent(sbd)) {
        if (debugEnabled) {
            logger.debug("Identified candidate component class: " + resource);
        }
        candidates.add(sbd);
    }
    else {
        if (debugEnabled) {
            logger.debug("Ignored because not a concrete top-level class: " + resource);
        }
    }
}

我们看第一层的判定方法,如果大家用过 excludeFilters、includeFilters注解或者在我们

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
    // 通过 excludeFilters 进行是否需要排除的
    for (TypeFilter tf : this.excludeFilters) {
        if (tf.match(metadataReader, getMetadataReaderFactory())) {
            return false;
        }
    }
    /**
	 * includeFilters 是否需要进行包含的,还记得我们之前在说明 ComponentScanBeanDefinitionParser#parse 时创建的解析类么?
	 * 会创建一个 ClassPathBeanDefinitionScanner 实例,在它的构造方法中初始化属性时,将 @Component 注册到了 includeFilters
	 */
    for (TypeFilter tf : this.includeFilters) {
        if (tf.match(metadataReader, getMetadataReaderFactory())) {
            return isConditionMatch(metadataReader);
        }
    }
    return false;
}

看到这里,老铁,我们发现了重要的一个东西,@Component注解相关的,我们知道@Service、@Controller、@Repository 等注解其实是@Component 注解的拓展,其实他们都被@Component 修饰了的,这个基本操作我就补贴了,大家看各个注解就知道了。

所以这里!!!判定这个 class 是否被注解@Component 修饰了的,老铁!看到了吧,我们的@Controller、@Service、@Repository 也就是在这里解析了。

人才

registerComponents

我们先回到上面的registerComponents方法

protected void registerComponents(
    XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {

    Object source = readerContext.extractSource(element);
    CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);

    for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
        compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
    }

    // Register annotation config processors, if necessary.
    boolean annotationConfig = true;
    /**
	 * 默认 对注解的支持是 true 的, 所以在配置了 <context:component-scan>标签就不需要再配置<context:annotation-config>标签
	 */
    if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
        annotationConfig = Boolean.parseBoolean(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
    }
    if (annotationConfig) {
        Set<BeanDefinitionHolder> processorDefinitions =
            /**
			 * 注册注解处理器, 但是这里还没有开始处理注解, 要想使用注解处理器,必须要实例化注解处理器,那么其实例化是在哪里进行的呢,
			 * 这里还需要回到org.springframework.context.support.AbstractApplicationContext.java中的refresh()函数
			 * 对注解处理器 AutowiredAnnotationBeanPostProcessor 的实例化是在 registerBeanPostProcessors(beanFactory); 方法
			 * 因为它继承自 BeanPostProcessor,此类型的 bean 在 registerBeanPostProcessors 被实例化
			 */
            AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
        for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
            compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
        }
    }

    readerContext.fireComponentRegistered(compositeDef);
}

重点看:AnnotationConfigUtils#registerAnnotationConfigProcessors()

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
    BeanDefinitionRegistry registry, @Nullable Object source) {

    // 获取到 DefaultListableBeanFactory 类型的 beanfactory
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            // 将实现了 AnnotationAwareOrderComparator 接口的,Order 排序器注册到 beanfactory
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            // @Autowired 注解的候选的解析器,
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    // 固定 8 个。
    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

    /**
	 * 为我们容器中注册了解析我们配置类的后置处理器 ConfigurationClassPostProcessor
	 * 此类的全限定名称为:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
	 * 目前此类还没有被创建
	 */
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        // 调用 registry.registerBeanDefinition(beanName, definition) 将类注册到 BeanDefinition,然后包装返回一个 BeanDefinitionHolder 对象
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    /**
	 * 注册用于处理 @Autowired 注解的处理器 AutowiredAnnotationBeanPostProcessor
	 * 全限定类名:org.springframework.context.annotation.internalAutowiredAnnotationProcessor
	 * 目前此类还没有被创建
	 * 
	 * AutowiredAnnotationBeanPostProcessor 会:
	 * 扫描方法和属性上是否有@Autowired @Value注解
	 * 注意,@Autowired @Value 是 Spring 的注解
	 */
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    /**
	 * 注册用于处理 @Required 属性的注解处理器
	 *
	 * CommonAnnotationBeanPostProcessor 会:
	 * 扫描方法上是否有@PostConstruct @PreDestroy注解
	 * 扫描方法和属性上是否有@Resource注解
	 * 注意,@Resource @PostConstruct @PreDestroy 是 JDK 的注解
	 */
    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    /**
	 * 注册处理 JPA 主持的处理器 PersistenceAnnotationBeanPostProcessor
	 * 全限定类名:org.springframework.context.annotation.internalPersistenceAnnotationProcessor
	 */
    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                                                AnnotationConfigUtils.class.getClassLoader()));
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    /**
	 * 处理监听方法 @EventListener 的注解解析器 EventListenerMethodProcessor
	 */
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    /**
	 * 注册事件监听器工厂 DefaultEventListenerFactory
	 */
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

看到这里我们有点眉目了,注解 @Autowired 的解析器在这一步进行了注册,但是什么时候去解析呢?

大家洗把脸,清醒一下思路。

我们最先开始是从ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();进入分析的,分析完之后,我们了解到这个方法做了几件事:

  • 1、创建 BeanFactory 并实例化初始化
  • 2、解析配置文件的自定义标签,扫包得到被@Component【@Controller、@Service、@Repository 】 注解的 class,生成 BeanDefinition
  • 3、注册了很多注解解析器,但是没有实例化他们

@Controller、@Service、@Repository这几个注解我后面不再详细列出,我使用@Component的时候大家自己脑补这部分。

我们完成了问题的一部分,那么我们继续看 @Autowired 注解的解析。

registerBeanPostProcessors(beanFactory);方法

老铁们,抄作业!!!我们先在invokeBeanFactoryPostProcessors(beanFactory);这个方法 debug 断点一下,查看下

image-20200427110618328

同时查看下 singletonObjects,发现没有我们期望的任何实例化,说明注解处理器还没有实例化。

image-20200427110639611

先步进到下一步,还是没有我们期望的【虽然部分 processor 被实例化了。比如 ConfigurationAnnotationProcessor,这个处理器是用来处理@Configuration 注解的,但是我们先不讨论。】我们希望的是有类似关键字 AutowiredAnnotation之类的。

image-20200427110740946

再到下一步registerBeanPostProcessors(beanFactory);

image-20200427112057184

!!!看到了吧,老铁经过这个方法,发现注解处理器被实例化了,并且加入到了 singletonObjects。不知道 singletonObjects 的老铁补一下 spring 源码的相关知识。

我们知道在前面注册了注解处理器,其中@Autowired 的解析器AutowiredAnnotationBeanPostProcessor看到这个类名是不是超级熟悉,回顾一下我们的 3 个 PostProcessor

  • BeanDefinitionRegistryPostProcessor
  • BeanFactoryPostProcessor
  • BeanPostProcessor

AutowiredAnnotationBeanPostProcessor的父类一顿找,找到了它继承自BeanPostProcessor

registerBeanPostProcessors(beanFactory);方法名称也很好的解释了它的作用,注册解析器。

但是!!!老铁们,注意这个方法和上一步的invokeBeanFactoryPostProcessors的区别,上一步实例化了方法,并且调用了他们的 PostProcessor 方法,但是这里没有调用方法,只是将解析器实例化之后注册到 BeanFactory

迷茫

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);方法

上一步得到了注解解析器,并且实例化了,什么时候调用他们去解析注解呢?

我们跟进到方法finishBeanFactoryInitialization(beanFactory);找到实例化 bean 的时候的方AbstractAutowireCapableBeanFactory#doCreateBean

// 实例化 bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
// 初始化前置处理器,对 @Autowired 预处理
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
/**
 * bean 属性进行赋值 (调用set方法进行赋值) 依赖注入在这里【@Autowired处理器的调用】
 */
populateBean(beanName, mbd, instanceWrapper);
/**
 * 进行对象初始化操作 (在这里可能生成代理对象)
 */
exposedObject = initializeBean(beanName, exposedObject, mbd);

我这里列出了 4 个比较重要的方法,

  • 1、createBeanInstance(beanName, mbd, args):负责 bean 的实例化,但是还没有属性赋值;主要是通过各种构造方法,反射之类的技术,当然也涉及到了一些注解用法,但是不是我们的重点,我们只看常规操作的。
  • 2、applyMergedBeanDefinitionPostProcessors:这里去解析 @Autowired 注解,做预处理,我们后面跟进。
  • 3、populateBean:属性赋值,上面只是知道了某些属性或者方法被注解了,但是值是在这个方法赋予的,spring 设计的真牛
  • 4、initializeBean:初始化 bean,也不是我们当前文章的讨论重点,略过。
applyMergedBeanDefinitionPostProcessors方法

我们在这个方法上打断点,spring 在对所有 singleton 的 bean 初始化的时候会走到这里,我们跳过

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof MergedBeanDefinitionPostProcessor) {
            MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
            /**
			 * 如果是解析 @Configuration 注解,走的是 CommonAnnotationBeanPostProcessor 的方法
			 * 如果是解析 @Autowired 注解,走的是 和 AutowiredAnnotationBeanPostProcessor 的方法
			 */
            bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
    }
}

因为我们分析的是 @Autowired 注解,我们跟进到AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

然后在它的第一行打断点,再次跑起debug,我们跳过几个 bean 的实例,找到 ioc2 的实例化,因为这个类才有@Autowired 注解。

image-20200427132543226

从左边的调用栈我们知道这个方法的来源路径。

postProcessMergedBeanDefinition方法

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

findAutowiringMetadata方法,就是将 beanName 和其中被注解修饰的属性和方法存入 map 管理缓存起来。

// 看这个方法
metadata = buildAutowiringMetadata(clazz);
/**
 * 使用一个 ConcurrentHashMap 存储 bean 和注解属性方法的相关关系。
 * key = beanName,
 * value = 这个 bean 中被@Autowired注解的 field 和 method 信息,
 */
this.injectionMetadataCache.put(cacheKey, metadata);

buildAutowiringMetadata(clazz)有个很重要的点。

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
        return InjectionMetadata.EMPTY;
    }

    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

        /**
		 * 利用反射工具类,找到所有的属性,然后去循环得到的属性,找到被 @Autowired 注解的属性
		 */
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            /**
			 * 见名知意,查询是否有被 @Autowired 注解属性。
			 */
            MergedAnnotation<?> ann = findAutowiredAnnotation(field);
            if (ann != null) {
                /**
				 * @Autowired 不支持注解在 static 修饰的 field 上
				 */
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                /**
				 * 注解是否有 required 参数, @Autowired(required = true)
				 * 默认是 true
				 */
                boolean required = determineRequiredStatus(ann);
                /**
				 * 然后构建 AutowiredFieldElement 临时存储到 currElements,最后都会存储到 InjectionMetadata
				 * !!!!!!
				 * 记住这个方法调用,最后我们在对属性赋值的时候还会看到的。在 new AutowiredFieldElement 的时候
				 * 会调用它的父类 InjectedElement 的构造函数,将 field 赋值给了 InjectedElement#member
				 * 记住这个!!!
				 * 
				 * 既然我们都得到了属性了,下一步就应该是只需要给这个 field 赋值就好了,那么在哪里做到的呢?
				 * 我们当前还在 applyMergedBeanDefinitionPostProcessors 方法
				 * 具体的赋值是在 AbstractAutowireCapableBeanFactory#populateBean 方法中
				 */
                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);

    // 数据最后都缓存到 AutowiredAnnotationBeanPostProcessor#injectionMetadataCache
    return InjectionMetadata.forElements(elements, clazz);
}

这里最好跟进一下 currElements.add(new AutowiredFieldElement(field, required));看看这个构造方法做了什么,主要是它的父类,this.member = field,我们看看执行完这一步得到的内容:

image-20200428163108900

好了,我们知道了applyMergedBeanDefinitionPostProcessors方法其实就是将 bean 中的被注解的方法和方法提取缓存起来。

数据最后都缓存到 AutowiredAnnotationBeanPostProcessor#injectionMetadataCache

注解的生效逻辑是什么?

populateBean方法

终于快结束了,老铁们,坚持住。上面我们得到了被注解标注的属性和方法,然后结合学习 spring 源码时我们知道populateBean方法是组装属性赋值的,一定在这里搞事情。

我们直接看此方法的关键代码

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        /**
		 * 假设我们解析 @Autowired 注解,这里会调用 AutowiredAnnotationBeanPostProcessor 的方法。
		 * 之前我们知道通过 applyMergedBeanDefinitionPostProcessors 方法
		 * 将 bean 中被 @Autowried(当然还包括 @Value、@Inject)修饰的field、method找出来,封装成 InjectionMetadata 对象并缓存起来了。这里就是负责赋值的。
		 */
        PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
        if (pvsToUse == null) {
            if (filteredPds == null) {
                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            /**
			 * 对所有标记 @Autowired、@Value 注解的属性进行设置
			 */
            pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                return;
            }
        }
        pvs = pvsToUse;
    }
}

得到所有的 BeanPostProcessor,循环对比,我们关注的是 AutowiredAnnotationBeanPostProcessor。

image-20200427141600601

我们看AutowiredAnnotationBeanPostProcessor#postProcessProperties

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    /**
	 * 此时可以从缓存 injectionMetadataCache【一个 ConcurrentHashMap】 直接得到需要的 bean 和被 @Autowired 修饰的 field、method 关系。
	 * 缓存这一步是在 applyMergedBeanDefinitionPostProcessors(mbd, beanType, 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;
}

一步一步的跟进,我们到了AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject,因为我们关注的是 field 的注入,另外如果是方法的注入,就是 AutowiredMethodElement#inject

开始注入属性值

/**
 * 字段的依赖注入,另外还有方法的依赖注入,
 * @param bean
 * @param beanName
 * @param pvs
 * @throws Throwable
 */
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    /**
	 * !!!!!
	 * 得到我们需要赋值的那个属性,记得在 AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
	 * 我们缓存了需要的属性么
	 */
    Field field = (Field) this.member;
    Object value;
    // 尝试从缓存拿
    if (this.cached) {
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    }
    else {
        /**
		 * field 包装为 DependencyDescriptor
		 */
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
        Assert.state(beanFactory != null, "No BeanFactory available");
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        try {
            /**
			 * 我们以 demo 为例,解析 beanName = ioc2 的 Autowired 属性 desc = field iocService
			 * 先依据 type 获取【如果依赖的 bean 没有实例化,就去实例化】
			 * 核心方法还是在 BeanFactory 中,这一步就得到了属性的具体实例了。
			 * 调用 DefaultListableBeanFactory#doResolveDependency
			 */
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        /**
		 * 缓存一下 field 注入多次可以提高效率。
		 */
        synchronized (this) {
            if (!this.cached) {
                if (value != null || this.required) {
                    this.cachedFieldValue = desc;
                    /**
					 * 将当前 bean 和需要依赖的 bean 的依赖关系存到 BeanFactory 的 dependentBeanMap
					 * 比如 demo 的 ioc2 有属性 private IOCService iocService,依赖于 iocService,
					 * key = ioc2,value = Set<String>
					 */
                    registerDependentBeans(beanName, autowiredBeanNames);
                    // autowiredBeanNames 别名时,size 可能大于 1
                    if (autowiredBeanNames.size() == 1) {
                        String autowiredBeanName = autowiredBeanNames.iterator().next();
                        /**
						 * 需要依赖的 bean 是否已经在 BeanFactory 实例化了。
						 * 从 singletonObjects 或者 BeanDefinitionMap 得到,顺便看看是否是 FactoryBean
						 * 没找到就从父容器找,【springmvc 时才涉及到父容器】
						 */
                        if (beanFactory.containsBean(autowiredBeanName) &&
                            // @Autowired 是类型注入,这里检查下 type
                            beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                            // 这里缓存
                            this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                desc, autowiredBeanName, field.getType());
                        }
                    }
                }
                else {
                    this.cachedFieldValue = null;
                }
                this.cached = true;
            }
        }
    }
    if (value != null) {
        /**
		 * 利用反射方法 将一个字段设置为可读写,主要针对private字段;
		 * 这里就是将 ioc2 的 iocService 属性设置为可读写。
		 */
        ReflectionUtils.makeAccessible(field);
        /**
		 * 属性赋值完成,之后,ioc2 的 iocService 就有对应的实例了。
		 */
        field.set(bean, value);
    }
}
}

上面的代码我们终于看到了想要的,@Autowired注解的属性在这里被注入了。

---beanFactory.resolveDependency中方法的大致流程
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
org.springframework.beans.factory.config.DependencyDescriptor#resolveCandidate
beanfactory.getBean(xx);

撒花

Annotation 方式启动项目

注解什么时候被解析

代码

@Configuration
@ComponentScan(basePackages = {"top.ybq.ioc.beanlifecycle.annotation"})
public class MyAnnotationConfig {   
}
public class MainAnnotationStart {
    
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MyAnnotationConfig.class);
        String[] names = ac.getBeanFactory().getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }
}

具体的代码参考我的项目:[email protected]:Lingouzi/spring-framework.git

invokeBeanFactoryPostProcessors

不说废话,断点到AbstractApplicationContext#invokeBeanFactoryPostProcessors

发现这时BeanFactory#beanDefinitionNames 只有我们的配置类被解析(这里涉及到@Configuration 注解的解析,不展开,不是本文重点),而且 singletonObjects 中也只有 3 个环境变量的实例。

步进到下一步,发现beanDefinitionNames已经有了所有的BeanDefinition 了,所以注解模式下的扫包解析所有 BeanDefinition 应该是在invokeBeanFactoryPostProcessors这个方法进行的【xml 的方式是在obtainFreshBeanFactory()就完成了扫包解析了】。

跟进到PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

不废话,断点到这个方法里面第一次调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);方法一行。

然后对比下执行这行之后 BeanFactory#beanDefinitionNames的内容改变情况。

执行之前:

image-20200428173257461

执行之后:

image-20200428173331795

看回这个方法,他回去执行BeanDefinitionRegistryPostProcessor的回调,而分析得到第一个属于此类型的 class 正是ConfigurationClassPostProcessor,但是要执行这个方法的回调就要先实例化它

// 得到 当前 BeanDefinitionRegistryPostProcessor 类型的 BeanDefinition
// 注解模式下找到了 internalConfigurationAnnotationProcessor
String[] postProcessorNames =
    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 循环
for (String ppName : postProcessorNames) {
    // 是否实现了 PriorityOrdered 接口【优先级】
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        /**
		 * 显式调用 getBean() 的方式获取出该对象,然后加入到我们上面定义的集合中。【目前方法还么有调用】
		 * 经过此步骤之后,beanfactory 中的 singletonObjects 中就有 4 个单例对象的,之前的 3 个是:systemEnvironment、environment、systemProperties
		 */
        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
        // 加入 processedBeans
        processedBeans.add(ppName);
    }
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 记录
registryProcessors.addAll(currentRegistryProcessors);
/**
 * 回调方法, 注解模式下就是调用 ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
 */
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

那么这个internalConfigurationAnnotationProcessor的 BeanDefinition 又是哪里来的呢?

我们使用

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MyAnnotationConfig.class);

启动时,调用了AnnotationConfigApplicationContext的构造方法,

public AnnotationConfigApplicationContext() {

    /**
     * 初始化 annotation 模式下的 bean 定义扫描器,
     *********
     * 注解模式下,一些内置的注解解析器在这里被解析【@configuration、@Autowired、@Required、事件监听器。】
     * internalConfigurationAnnotationProcessor 处理 @configuration 等
	 * internalAutowiredAnnotationProcessor 处理 @Autowired、@Inject、@Value 等
	 * internalCommonAnnotationProcessor 处理 @Resource 等
     * 这里注册了 5 个 BeanDefinition
     */
    this.reader = new AnnotatedBeanDefinitionReader(this);
    /**
     * 初始化 classpath 类型的 bean 定义扫描器
     */
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

AnnotatedBeanDefinitionReader:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    // 把 applicationcontext 对象赋值给 reader
    this.registry = registry;
    // 用于处理条件表达式 @Condition 注解
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    // 注册一些后置处理器类的 BeanDefinition ,用于支持 @Configuration、@Autowired、jpa、事件监听器等,只是注册BeanDefinition
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

下面就不继续跟进了,大家自己看看熟悉一下。

ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry

这个方法不展开了,它就是负责扫所有被注解的 class,解析为 BeanDefinition 存入 BeanFactory。

得到了 BeanDefinition 信息,实例化和初始化 bean 的时候就可以属性注入了,流程就和 xml 的一致了,不重复。

结束

经过上面一通分析,我们终于知道了@Autowired 的生效原理,以及她什么时候被解析,什么时候注入属性。

总结下我看源码的一点点经验,大家除了看一些关键的 do、parse 方法外,对象的构造方法一定不能漏了,spring 很多关键操作其实就是在构造函数中进行的。

典型的如注解的时候,默认注解解析器的注入this.reader = new AnnotatedBeanDefinitionReader(this); ,还有上面我强调的currElements.add(new AutowiredFieldElement(field, required))

好了,先到这里吧。

结束语

公众号二维码_8cm

欢迎转发和关注

公众号:林子曰

开源项目:[email protected]:Lingouzi/blog.git

版权声明:本文为qq_21019419原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_21019419/article/details/105826565