Spring 高级 @Autowired bean 后处理器运行分析

上篇:https://www.cnblogs.com/mangoubiubiu/p/16591665.html  知道了

AutowiredAnnotationBeanPostProcessor 执行依赖注入的时候,实际上是先调用了postProcessProperties方法,而postProcessProperties方法内部 分为2步去进行依赖注入,第一步是用findAutowiringMetadata方法找到某个类型中标注了@Autowired 方法 成员变量 收集起来,信息叫做InjectionMetadata,找到信息后 InjectionMetadata 执行 inject 才完成反射调用 进行依赖注入。

那么inject 内部是如何进行依赖注入的呢?

复制代码
package com.mangoubiubiu.show.a04;


import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class DigInAutowired {

    public static void main(String[] args) throws Throwable {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2",new Bean2());//创建过程,依赖注入,初始化
        beanFactory.registerSingleton("bean3",new Bean3());

        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());//value
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);
        //1、查找哪些属性、方法加了@Autowired,这称之为InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        //设置bean 工厂 让bean工厂去找Bean
        processor.setBeanFactory(beanFactory);

        //自己创建一个bean1 自己创建的并没有依赖注入
        Bean1 bean1 = new Bean1();

        System.out.println(bean1);

//        processor.postProcessProperties(null,bean1,"bean1");
        Method findAutowiringMetadata =  AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        //获取 Bean1 上加了 @Value @Autowired 的成员变量 , 方法参数
        InjectionMetadata metadata = (InjectionMetadata)findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);
        //进行依赖注入
        metadata.inject(bean1,"bean1",null);
        System.out.println(metadata);
        System.out.println(bean1);


        //成员变量的依赖注入
        Field bean3 = Bean1.class.getDeclaredField("bean3");
        //第二个成员变量  true  找不到就报错   false 找不到就找不到
        DependencyDescriptor dd1 = new DependencyDescriptor(bean3,false);
        //根据成员变量信息找成员变量类型,然后再在容器中找符合该类型的bean
        Object o = beanFactory.doResolveDependency(dd1, null, null, null);
        System.out.println(o);


        //方法上的依赖注入
        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);

        DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean2,0),false);

        Object os = beanFactory.doResolveDependency(dd2, null, null, null);
        System.out.println(os);


        //方法上的值注入
        Method setHomeAutowired = Bean1.class.getDeclaredMethod("setHomeAutowired", String.class);

        DependencyDescriptor dd3 = new DependencyDescriptor(new MethodParameter(setHomeAutowired,0),false);

        Object oss = beanFactory.doResolveDependency(dd3, null, null, null);
        System.out.println(oss);
    }
}
复制代码

总结:

  1. 很简单分三步,先找到 Bean3的成员变量封装成DependencyDescriptor
  2. 然后在调用beanFactory的方法在容器中找符合该类型的bean
  3. 完成依赖注入

注意:如果容器内没有该类型的bean 封装DependencyDescriptor时

boolean required = true 找不到是 会直接报错 boolean required = false 找不到返回null

复制代码
"C:\Program Files\Java\jdk1.8.0_202\bin\java.exe" "-javaagent:D:\development_tools\IntelliJ IDEA 2020.1.2\lib\idea_rt.jar=63875:D:\development_tools\IntelliJ IDEA 2020.1.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_202\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\rt.jar;E:\idea_workspace_study\show\target\classes;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\boot\spring-boot-starter-web\2.6.4\spring-boot-starter-web-2.6.4.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\boot\spring-boot-starter\2.6.4\spring-boot-starter-2.6.4.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\boot\spring-boot-starter-logging\2.6.4\spring-boot-starter-logging-2.6.4.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\ch\qos\logback\logback-classic\1.2.10\logback-classic-1.2.10.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\ch\qos\logback\logback-core\1.2.10\logback-core-1.2.10.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\apache\logging\log4j\log4j-to-slf4j\2.17.1\log4j-to-slf4j-2.17.1.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\apache\logging\log4j\log4j-api\2.17.1\log4j-api-2.17.1.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\slf4j\jul-to-slf4j\1.7.36\jul-to-slf4j-1.7.36.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\yaml\snakeyaml\1.29\snakeyaml-1.29.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\boot\spring-boot-starter-json\2.6.4\spring-boot-starter-json-2.6.4.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\com\fasterxml\jackson\core\jackson-databind\2.13.1\jackson-databind-2.13.1.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\com\fasterxml\jackson\core\jackson-annotations\2.13.1\jackson-annotations-2.13.1.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\com\fasterxml\jackson\core\jackson-core\2.13.1\jackson-core-2.13.1.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.13.1\jackson-datatype-jdk8-2.13.1.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.13.1\jackson-datatype-jsr310-2.13.1.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\com\fasterxml\jackson\module\jackson-module-parameter-names\2.13.1\jackson-module-parameter-names-2.13.1.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\boot\spring-boot-starter-tomcat\2.6.4\spring-boot-starter-tomcat-2.6.4.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\apache\tomcat\embed\tomcat-embed-core\9.0.58\tomcat-embed-core-9.0.58.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\apache\tomcat\embed\tomcat-embed-el\9.0.58\tomcat-embed-el-9.0.58.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.58\tomcat-embed-websocket-9.0.58.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\spring-web\5.3.16\spring-web-5.3.16.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\spring-beans\5.3.16\spring-beans-5.3.16.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\spring-webmvc\5.3.16\spring-webmvc-5.3.16.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\spring-aop\5.3.16\spring-aop-5.3.16.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\spring-context\5.3.16\spring-context-5.3.16.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\spring-expression\5.3.16\spring-expression-5.3.16.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\boot\spring-boot-devtools\2.6.4\spring-boot-devtools-2.6.4.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\boot\spring-boot\2.6.4\spring-boot-2.6.4.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\boot\spring-boot-autoconfigure\2.6.4\spring-boot-autoconfigure-2.6.4.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\projectlombok\lombok\1.18.22\lombok-1.18.22.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\slf4j\slf4j-api\1.7.36\slf4j-api-1.7.36.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\spring-core\5.3.16\spring-core-5.3.16.jar;D:\development_tools\maven\apache-maven-3.6.3\repo\org\springframework\spring-jcl\5.3.16\spring-jcl-5.3.16.jar" com.mangoubiubiu.show.a04.DigInAutowired
Bean1{bean2=null, bean3=null, home='null'}
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bean1': Unsatisfied dependency expressed through field 'bean3'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.mangoubiubiu.show.a04.Bean3' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:659)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
    at com.mangoubiubiu.show.a04.DigInAutowired.main(DigInAutowired.java:43)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.mangoubiubiu.show.a04.Bean3' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1799)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1355)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656)
    ... 3 more

Process finished with exit code 1
复制代码

 

 

本文作者:KwFruit

本文链接:https://www.cnblogs.com/mangoubiubiu/p/16591961.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   KwFruit  阅读(124)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起