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); } }
总结:
- 很简单分三步,先找到 Bean3的成员变量封装成DependencyDescriptor
- 然后在调用beanFactory的方法在容器中找符合该类型的bean
- 完成依赖注入
注意:如果容器内没有该类型的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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步