1. 依赖注入的模式和模型: Spring 提供了哪些依赖注入的模式和类型?
-  
手动模式 - 配置或者编程的方式,提前安排注入规则
- XML资源配置元信息
 - Java 注解配置元信息
 - API 配置元信息
 
 -  
自动模式 - 实现方提供依赖自动关联的方式,按照内建的注入规则
- Autowiring (自动绑定)
 
 -  
依赖注入类型

 
2. 自动绑定(Autowiring):为什么Spring会引入Autowiring?
-  
官方说明
-  
The Spring container can autowire relationships between collaborating beans. You can let Spring resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext.
spring容器能够通过自动绑定的关系, 在所谓的合作Bean之间(意思就是依赖类/被依赖类), 通过检查ApplicationContext的内容, 让spring能去处理这些合作者Bean。 
 -  
 -  
优点
-  
Autowiring can significantly reduce the need to specify properties or constructor arguments.
Autowiring 可以有效减少我们一些属性或构造器参数的一个设定 -  
Autowiring can update a configuration as your objects evolve.
自动绑定能更新配置, 就当你的对象正在被逐渐升级或逐渐形成的时候 
 -  
 
3. 自动绑定(Autowiring)模式:各种自动绑定模式的使用场景是什么?
-  
Autowiring modes
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2uOAbmv3-1669797885493)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124162056276.png)]](https://img-blog.csdnimg.cn/2e291ec997dd4d189366a8e9fd55c46f.png)
参考枚举: org.springframework. beans.factory.annotation.Autowire
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jp8xrNLT-1669797885494)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124164442428.png)]](https://img-blog.csdnimg.cn/01992505826b4c558cb3de9fc4e9b504.png)
为什么没有构造器模式, 因为构造器模式是一种特殊的BY_TYPE
 
4. 自动绑定(Autowiring)限制和不足:如何理解和挖掘官方文档中深层次的含义?
-  
官方说明
-  
Limitations and Disadvantages of Autowiring
-  
链接: https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/spring-framework-reference/core.html#beans-autowired-exceptions
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ddtYaJKU-1669797885494)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124173313184.png)]](https://img-blog.csdnimg.cn/3ce1708c048148eaaf4943654f407b6d.png)
 
 -  
 
 -  
 
5. Setter方法依赖注入:Setter注入的原理是什么?
-  
实现方法
-  
手动模式
-  
XML资源配置元信息
-  
dependency-lookup-context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 实施加载bean--> <bean id="user" class="org.xiaoge.thinking.in.spring.ioc.overview.domain.User"> <property name="id" value="1" /> <property name="name" value="xiaoge"/> </bean> <!-- 延迟bean 是沟通objectFactory简介创建的 --> <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"> <property name="targetBeanName" value="user" /> </bean> <!-- parent继承 --> <bean id="superUser" class="org.xiaoge.thinking.in.spring.ioc.overview.domain.SuperUser" parent="user" primary="true"> <property name="address" value="武汉" /> </bean> </beans> -  
dependency-setter-injection.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="classpath:/META-INF/dependency-lookup-context.xml"/> <!-- setter依赖注入 --> <bean class="org.xiaoge.thinking.in.spring.ioc.dependency.injection.UserHolder"> <property name="user" ref="user"></property> </bean> </beans> -  
UserHolder.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; /** * {@link org.xiaoge.thinking.in.spring.ioc.overview.domain.User} Holder 类 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class UserHolder { private User user; public UserHolder() { } public UserHolder(User user) { this.user = user; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public String toString() { return "UserHolder{" + "user=" + user + '}'; } } -  
XmlDependencySetterInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; /** * 基于 XML 资源的依赖 Setter 方法注入 示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class XmlDependencySetterInjectionDemo { public static void main(String[] args) { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); String xmlSourcePath = "classpath:/META-INF/dependency-setter-injection.xml"; // 加载 XML 资源, 解析并且生成 BeanDefinition xmlBeanDefinitionReader.loadBeanDefinitions(xmlSourcePath); // 依赖查找 并且 创建 Bean (注意: 依赖查找的过程中会伴随着创建Bean) UserHolder userHolder = beanFactory.getBean(UserHolder.class); System.out.println(userHolder); } } // 运行结果 UserHolder{user=User{id=1, name='xiaoge'}} 
 -  
 -  
.Java 注解配置元信息
-  
AnnotationDependencySetterInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; /** * 基于 注解 资源的依赖 Setter 方法注入 示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AnnotationDependencySetterInjectionDemo { public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencySetterInjectionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); UserHolder userHolder = applicationContext.getBean(UserHolder.class); System.out.println(userHolder); // 关闭应用上下文 applicationContext.close(); } /** * 加@Qualifier是通过Bean名称, 没加是通过Bean类型去找User * @param user * @return */ @Bean public UserHolder userHolder(@Qualifier("user") User user) { UserHolder userHolder = new UserHolder(); userHolder.setUser(user); return userHolder; } } // 运行结果 UserHolder{user=User{id=1, name='xiaoge'}} 
 -  
 -  
API 配置元信息
-  
ApiDependencySetterInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; /** * 基于 API 资源的依赖 Setter 方法注入 示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class ApiDependencySetterInjectionDemo { public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 生成 UserHolder 的 BeanDefinition BeanDefinition userHolderBeanDefinition = createUserHolderBeanDefinition(); // 注册 UserHolder 的 BeanDefinition applicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); UserHolder userHolder = applicationContext.getBean(UserHolder.class); System.out.println(userHolder); // 关闭应用上下文 applicationContext.close(); } /** * 为 {@link UserHolder} 生成 {@link BeanDefinition} * @return */ private static BeanDefinition createUserHolderBeanDefinition() { BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class); // 设置属性值 beanDefinitionBuilder.addPropertyReference("user", "user"); return beanDefinitionBuilder.getBeanDefinition(); } } // 运行结果 UserHolder{user=User{id=1, name='xiaoge'}} 
 -  
 
 -  
 -  
自动模式
-  
byName
-  
autowiring-dependency-setter-injection.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="classpath:/META-INF/dependency-lookup-context.xml"/> <!-- setter依赖注入 --> <bean class="org.xiaoge.thinking.in.spring.ioc.dependency.injection.UserHolder" autowire="byName"> </bean> </beans> -  
AutowiringByNameDependencySetterInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; /** * "byName/byType" Autowiring 依赖 setter 注入示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AutowiringByNameDependencySetterInjectionDemo { public static void main(String[] args) { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); String xmlSourcePath = "classpath:/META-INF/autowiring-dependency-setter-injection.xml"; // 加载 XML 资源, 解析并且生成 BeanDefinition xmlBeanDefinitionReader.loadBeanDefinitions(xmlSourcePath); // 依赖查找 并且 创建 Bean (注意: 依赖查找的过程中会伴随着创建Bean) UserHolder userHolder = beanFactory.getBean(UserHolder.class); System.out.println(userHolder); } } // 运行结果 UserHolder{user=User{id=1, name='xiaoge'}} 
 -  
 -  
byType
-  
autowiring-dependency-setter-injection.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="classpath:/META-INF/dependency-lookup-context.xml"/> <!-- setter依赖注入 --> <bean class="org.xiaoge.thinking.in.spring.ioc.dependency.injection.UserHolder" autowire="byType"> </bean> </beans> -  
AutowiringByNameDependencySetterInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; /** * "byName/byType" Autowiring 依赖 setter 注入示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AutowiringByNameDependencySetterInjectionDemo { public static void main(String[] args) { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); String xmlSourcePath = "classpath:/META-INF/autowiring-dependency-setter-injection.xml"; // 加载 XML 资源, 解析并且生成 BeanDefinition xmlBeanDefinitionReader.loadBeanDefinitions(xmlSourcePath); // 依赖查找 并且 创建 Bean (注意: 依赖查找的过程中会伴随着创建Bean) UserHolder userHolder = beanFactory.getBean(UserHolder.class); System.out.println(userHolder); } } // 运行结果 UserHolder{user=SuperUser{address='武汉'} User{id=1, name='xiaoge'}} 因为superUser加了primary="true" 
 -  
 
 -  
 
 -  
 
6. 构造器依赖注入:官方为什么推荐使用构造器注入?
-  
实现方法
-  
手动模式
-  
XML 资源配置元信
-  
dependency-constructor-injection.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="classpath:/META-INF/dependency-lookup-context.xml"/> <!-- setter依赖注入 --> <bean class="org.xiaoge.thinking.in.spring.ioc.dependency.injection.UserHolder"> <constructor-arg name="user" ref="superUser"></constructor-arg> </bean> </beans> -  
1
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; /** * 基于 XML 资源的依赖 Constructor 注入 示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class XmlDependencyConstructorInjectionDemo { public static void main(String[] args) { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); String xmlSourcePath = "classpath:/META-INF/dependency-constructor-injection.xml"; // 加载 XML 资源, 解析并且生成 BeanDefinition xmlBeanDefinitionReader.loadBeanDefinitions(xmlSourcePath); // 依赖查找 并且 创建 Bean (注意: 依赖查找的过程中会伴随着创建Bean) UserHolder userHolder = beanFactory.getBean(UserHolder.class); System.out.println(userHolder); } } // 运行结果 UserHolder{user=SuperUser{address='武汉'} User{id=1, name='xiaoge'}} 
 -  
 -  
Java 注解配置元信息
-  
AnnotationDependencyConstructorInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; /** * 基于 注解 资源的依赖 Constructor 注入 示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AnnotationDependencyConstructorInjectionDemo { public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencyConstructorInjectionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); UserHolder userHolder = applicationContext.getBean(UserHolder.class); System.out.println(userHolder); // 关闭应用上下文 applicationContext.close(); } /** * 加@Qualifier是通过Bean名称, 没加是通过Bean类型去找User * @param user * @return */ @Bean public UserHolder userHolder(@Qualifier("user") User user) { return new UserHolder(user); } } // 运行结果 UserHolder{user=User{id=1, name='xiaoge'}} 
 -  
 -  
API 配置元信息
-  
ApiDependencyConstructorInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * 基于 API 资源的依赖 Constructor 注入 示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class ApiDependencyConstructorInjectionDemo { public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 生成 UserHolder 的 BeanDefinition BeanDefinition userHolderBeanDefinition = createUserHolderBeanDefinition(); // 注册 UserHolder 的 BeanDefinition applicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); UserHolder userHolder = applicationContext.getBean(UserHolder.class); System.out.println(userHolder); // 关闭应用上下文 applicationContext.close(); } /** * 为 {@link UserHolder} 生成 {@link BeanDefinition} * @return */ private static BeanDefinition createUserHolderBeanDefinition() { BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class); // 构造器设置属性值, 这个只有一个参数, 构造器如果有3个参数, 依次调三次这个方法addConstructorArgReference, 我这里只有一个所以写一次 beanDefinitionBuilder.addConstructorArgReference("superUser"); return beanDefinitionBuilder.getBeanDefinition(); } } // 运行结果 UserHolder{user=SuperUser{address='武汉'} User{id=1, name='xiaoge'}} 
 -  
 
 -  
 -  
自动模式
-  
constructor
-  
autowiring-dependency-constructor-injection.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="classpath:/META-INF/dependency-lookup-context.xml"/> <!-- setter依赖注入 --> <bean class="org.xiaoge.thinking.in.spring.ioc.dependency.injection.UserHolder" autowire="constructor"> </bean> </beans> -  
AutowiringConstructorDependencyConstructorInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; /** * "constructor" Autowiring 依赖 Constructor 注入示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AutowiringConstructorDependencyConstructorInjectionDemo { public static void main(String[] args) { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); String xmlSourcePath = "classpath:/META-INF/autowiring-dependency-constructor-injection.xml"; // 加载 XML 资源, 解析并且生成 BeanDefinition xmlBeanDefinitionReader.loadBeanDefinitions(xmlSourcePath); // 依赖查找 并且 创建 Bean (注意: 依赖查找的过程中会伴随着创建Bean) UserHolder userHolder = beanFactory.getBean(UserHolder.class); System.out.println(userHolder); } } // 运行结果 UserHolder{user=SuperUser{address='武汉'} User{id=1, name='xiaoge'}} 
 -  
 
 -  
 
 -  
 
7. 字段注入:为什么Spring官方文档没有单独列举这种注入方式?
-  
实现方法
-  
手动模式
-  
Java 注解配置元信息
-  
@Autowired
 -  
@Resource
 -  
@Inject(可选)
 -  
AnnotationDependencyFieldInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import javax.annotation.Resource; /** * 基于 注解 资源的依赖 Field 注入 示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AnnotationDependencyFieldInjectionDemo { @Autowired private // static @Autowired 会忽略掉静态字段 所以加嘞static userHolder为null UserHolder userHolder; @Resource // @Resource 标注的字段同理 不能为static 为static就会报错 private UserHolder userHolder2; public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencyFieldInjectionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); AnnotationDependencyFieldInjectionDemo demo = applicationContext.getBean(AnnotationDependencyFieldInjectionDemo.class); System.out.println(demo.userHolder); System.out.println(demo.userHolder2); System.out.println(demo.userHolder == demo.userHolder2); // 关闭应用上下文 applicationContext.close(); } /** * 加@Qualifier是通过Bean名称, 没加是通过Bean类型去找User * @param user * @return */ @Bean public UserHolder userHolder(@Qualifier("user") User user) { return new UserHolder(user); } } // 运行结果 UserHolder{user=User{id=1, name='xiaoge'}} UserHolder{user=User{id=1, name='xiaoge'}} true所以这里指的字段注入, 是指的实例字段/对象字段
 
 -  
 
 -  
 
 -  
 
8. 方法注入:方法注入是@Autowired专利吗?
-  
实现方法
-  
手动模式
-  
Java 注解配置元信息
-  
@Autowired
 -  
@Resource
 -  
@Inject(可选)
 -  
@Bean
 -  
AnnotationDependencyMethodInjectionDemo
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import javax.annotation.Resource; /** * 基于 注解 资源的依赖 Method 注入 示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AnnotationDependencyMethodInjectionDemo { private UserHolder userHolder; private UserHolder userHolder2; @Autowired public void initUserHolder(UserHolder userHolder) { this.userHolder = userHolder; } @Resource public void initUserHolder2(UserHolder userHolder2) { this.userHolder2 = userHolder2; } /** * 加@Qualifier是通过Bean名称, 没加是通过Bean类型去找User * @param user * @return */ @Bean public UserHolder userHolder(@Qualifier("user") User user) { return new UserHolder(user); } public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencyMethodInjectionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); AnnotationDependencyMethodInjectionDemo demo = applicationContext.getBean(AnnotationDependencyMethodInjectionDemo.class); System.out.println(demo.userHolder); System.out.println(demo.userHolder2); System.out.println(demo.userHolder == demo.userHolder2); // 关闭应用上下文 applicationContext.close(); } } // 运行结果 UserHolder{user=User{id=1, name='xiaoge'}} UserHolder{user=User{id=1, name='xiaoge'}} true注意: 方法注入只关注方法参数类型(不关注方法名称, 方法名称可以随便写), 它会去spring上下文中去找对应类型的对象赋值给方法的参数
 
 -  
 
 -  
 
 -  
 
9. 接口回调注入:回调注入的使用场景和限制有哪些?
-  
Aware 系列接口回调
-  
自动模式
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LDRF49VT-1669797885494)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125152547024.png)]](https://img-blog.csdnimg.cn/74b3cadc105540e09bfc136ca08dc490.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nysGzMrK-1669797885494)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125152604985.png)]](https://img-blog.csdnimg.cn/638318f194cc44d5a87bb7f7b4a06c03.png)
AwareInterfaceDependencyInjectionDemo.java
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.BeansException; import org.springframework.beans.factory.Aware; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * 基于 ${@link Aware} 接口回调的依赖注入 示例 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AwareInterfaceDependencyInjectionDemo implements BeanFactoryAware, ApplicationContextAware { private static BeanFactory beanFactory; private static ApplicationContext applicationContext; public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 -> springBean context.register(AwareInterfaceDependencyInjectionDemo.class); // 启动应用上下文 context.refresh(); /* 因为 AnnotationConfigApplicationContext 本身没有能力去获取Bean 它是通过context.getBeanFactory()获取DefaultListableBeanFactory对象去查询bean */ System.out.println(AwareInterfaceDependencyInjectionDemo.beanFactory == context.getBeanFactory()); System.out.println(applicationContext == context); // 关闭应用上下文 context.close(); } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { AwareInterfaceDependencyInjectionDemo.beanFactory = beanFactory; } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { AwareInterfaceDependencyInjectionDemo.applicationContext = applicationContext; } } // 运行结果 true true 
 -  
 
10. 依赖注入类型选择:各种依赖注入有什么样的使用场景?
- 注入选型 
  
- 低依赖:构造器注入 
    
- 超过三个参数建议用Setter方式
 
 - 多依赖:Setter 方法注入 
    
- Setter注入也有一个弊端, setter注入, 它的先后顺序, 使我们开发者使用来觉得的, 这样就会产生一个问题, 字段依赖的时候, 我们必须要先注入谁, 在注入谁, 要思路清晰
 
 - 便利性:字段注入
 - 声明类:方法注入 
    
- 建议使用@Bean注解, 不推荐使用@Autowired/@Resource
 
 
 - 低依赖:构造器注入 
    
 
11. 基础类型注入:String和Java原生类型也能注入Bean的属性,它们算依赖注入吗?
-  
基础类型
-  
原生类型(Primitive):boolean、byte、char、short、int、float、long、double
 -  
标量类型(Scalar):Number、Character、Boolean、Enum、Locale、Charset、Currency、 Properties、UUID
 -  
常规类型(General):Object、String、TimeZone、Calendar、Optional 等
 -  
Spring 类型:Resource、InputSource、Formatter 等
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4FJ3Giot-1669797885495)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164309237.png)]](https://img-blog.csdnimg.cn/66277f1842764621b4471a990d2f9335.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b74KpryM-1669797885495)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164429336.png)]](https://img-blog.csdnimg.cn/0016c65bb02f4c51abc31421fb01cf31.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WAFGUlCe-1669797885495)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164444863.png)]](https://img-blog.csdnimg.cn/e3a4be7163e8410f82b2952badd3d650.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZjjZPcCU-1669797885496)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164517057.png)]](https://img-blog.csdnimg.cn/163c916abace445bb5607855af0585d3.png)
resource为什么打印出来会有class path resource因为它是掉的ClassPathResource的toString方法
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A0BFgnvq-1669797885496)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164713707.png)]](https://img-blog.csdnimg.cn/7b3fd317d3dc4331b0500fc4d0638581.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dRkNSeuA-1669797885496)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164724118.png)]](https://img-blog.csdnimg.cn/be85da04132d443e91a9ecc1d464cbec.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DMWWKScN-1669797885496)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164750366.png)]](https://img-blog.csdnimg.cn/9c1d6ae89be34f64a4d387bd9754d1b3.png)
 
 -  
 
12. 集合类型注入:注入Collection和Map类型的依赖区别?还支持哪些集合类型?
-  
集合类型
-  
数组类型(Array):原生类型、标量类型、常规类型、Spring 类
 -  
集合类型(Collection)
-  
Collection:List、Set(SortedSet、NavigableSet、EnumSet)
 -  
Map:Properties
 -  
User.java
package org.xiaoge.thinking.in.spring.ioc.overview.domain; import org.omg.CORBA.PRIVATE_MEMBER; import org.springframework.core.io.Resource; import org.xiaoge.thinking.in.spring.ioc.overview.Enum.City; import java.util.Arrays; import java.util.List; import java.util.Map; /** * @Classname User * @Date 2022/10/17 14:57 * @Created by ZhangXiao * @Description TODO */ public class User { private Long id; private String name; private City city; private Resource configFileLocation; private City[] workCities; private List<City> lifeCities; private Map<Object, Object> map; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public City getCity() { return city; } public void setCity(City city) { this.city = city; } public Resource getConfigFileLocation() { return configFileLocation; } public void setConfigFileLocation(Resource configFileLocation) { this.configFileLocation = configFileLocation; } public City[] getWorkCities() { return workCities; } public void setWorkCities(City[] workCities) { this.workCities = workCities; } public List<City> getLifeCities() { return lifeCities; } public void setLifeCities(List<City> lifeCities) { this.lifeCities = lifeCities; } public Map<Object, Object> getMap() { return map; } public void setMap(Map<Object, Object> map) { this.map = map; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", city=" + city + ", configFileLocation=" + configFileLocation + ", workCities=" + Arrays.toString(workCities) + ", lifeCities=" + lifeCities + ", map=" + map + '}'; } public static User createUser() { User user = new User(); user.setId(1L); user.setName("xiaoge"); return user; } } -  
dependency-lookup-context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 实施加载bean--> <bean id="user" class="org.xiaoge.thinking.in.spring.ioc.overview.domain.User"> <property name="id" value="1" /> <property name="name" value="xiaoge"/> <property name="city" value="WUHAN"/> <property name="configFileLocation" value="classpath:/META-INF/dependency-lookup-context.xml"/> <property name="workCities" value="WUHAN, HANGZHOU"/> <!-- <property name="lifeCities" value="WUHAN, BEIJING"/>--> <property name="lifeCities"> <list> <value>WUHAN</value> <value>BEIJING</value> </list> </property> <property name="map"> <map> <entry key="one" value="1" /> <entry key="two" value="2" /> </map> </property> </bean> <!-- 延迟bean 是沟通objectFactory简介创建的 --> <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"> <property name="targetBeanName" value="user" /> </bean> <!-- parent继承 --> <bean id="superUser" class="org.xiaoge.thinking.in.spring.ioc.overview.domain.SuperUser" parent="user" primary="true"> <property name="address" value="武汉" /> </bean> </beans> -  
DependencyLookupDemo.java
package org.xiaoge.thinking.in.spring.ioc.overview.dependency.lookup; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.ObjectFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.xiaoge.thinking.in.spring.ioc.overview.annotation.Super; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import java.util.Map; /** * 依赖查找示例 * 1. 通过名称的方式查找 * 1. 实时查找 lookupInRealTime * 2. 延迟查找 lookupInLazy * 2. 根据类型查找 * 1. 根据类型查找单个bean lookupByType * 2. 根据类型查找集合对象Map<beanid, bean集合> lookupCollectionByType * 3. 根据java注解查找 * 1. 单个bean对象/集合bean对象 lookupAnnotationByType * * @Classname DependencyLookupDemo * @Date 2022/10/17 14:56 * @Created by ZhangXiao * @Description TODO */ public class DependencyLookupDemo { public static void main(String[] args) { // 配置xml配置文件 // 启动spring应用上下文 BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:META-INF/dependency-lookup-context.xml"); lookupInRealTime(beanFactory); lookupInLazy(beanFactory); lookupByType(beanFactory); lookupCollectionByType(beanFactory); lookupAnnotationByType(beanFactory); } /** * 根据注解查找集合对象 * @param beanFactory */ private static void lookupAnnotationByType(BeanFactory beanFactory) { if (beanFactory instanceof ListableBeanFactory) { ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory; Map<String, User> map = (Map)listableBeanFactory.getBeansWithAnnotation(Super.class); System.out.println("查找所有标注: @Super 所有的 user 集合对象: " + map); } } /** * 根据类型查找集合对象 * @param beanFactory */ private static void lookupCollectionByType(BeanFactory beanFactory) { if (beanFactory instanceof ListableBeanFactory) { ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory; Map<String, User> map = listableBeanFactory.getBeansOfType(User.class); System.out.println("查找到所有的 user 集合对象: " + map); } } /** * 根据类型实时查找 * @param beanFactory */ private static void lookupByType(BeanFactory beanFactory) { User user = beanFactory.getBean(User.class); System.out.println("实时查找: " + user); } /** * 延迟加载bean * @param beanFactory */ public static void lookupInLazy(BeanFactory beanFactory) { ObjectFactory<User> objectFactory = (ObjectFactory<User>)beanFactory.getBean("objectFactory"); User user = objectFactory.getObject(); System.out.println("延迟查找: " + user); } /** * 实施加载bean * @param beanFactory */ public static void lookupInRealTime(BeanFactory beanFactory) { User user = (User)beanFactory.getBean("user"); System.out.println("实时查找: " + user); } } // 运行结果 实时查找: User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} 延迟查找: User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} 实时查找: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} 查找到所有的 user 集合对象: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}} 查找所有标注: @Super 所有的 user 集合对象: {superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}} 
 -  
 
 -  
 
13. 限定注入:如何限定Bean名称注入?如何实现Bean逻辑分组注入?
-  
使用注解 @Qualifier 限定
-  
通过 Bean 名称限定
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; /** * {@link Qualifier} 注解依赖注入 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @see Qualifier * @since */ public class QualifierAnnotationDependencylrjectionDemo { @Autowired private User user; // super user -> primary = true @Autowired @Qualifier("user") private User namedUser; // 指定 Bean 名称 或 ID public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(QualifierAnnotationDependencylrjectionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); QualifierAnnotationDependencylrjectionDemo demo = applicationContext.getBean(QualifierAnnotationDependencylrjectionDemo.class); System.out.println("demo.user: " + demo.user); System.out.println("demo.namedUser: " + demo.namedUser); // 关闭应用上下文 applicationContext.close(); } } // 运行结果 demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.namedUser: User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} -  
通过分组限定
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import java.util.Collection; /** * {@link Qualifier} 注解依赖注入 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @see Qualifier * @since */ public class QualifierAnnotationDependencylrjectionDemo { @Autowired private User user; // super user -> primary = true @Autowired @Qualifier("user") private User namedUser; // 指定 Bean 名称 或 ID @Autowired // 只会获取不带Qualifier的Bean private Collection<User> allUsers; // 2 Bean -> super user, user @Autowired @Qualifier // 只会获取带Qualifier的Bean private Collection<User> qualifierUsers; // 2 Bean -> user1, user2 @Bean @Qualifier // 进行逻辑分组 public User user1() { User user = new User(); user.setId(7L); return user; } @Bean @Qualifier // 进行逻辑分组 public User user2() { User user = new User(); user.setId(8L); return user; } public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(QualifierAnnotationDependencylrjectionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); QualifierAnnotationDependencylrjectionDemo demo = applicationContext.getBean(QualifierAnnotationDependencylrjectionDemo.class); System.out.println("demo.user: " + demo.user); System.out.println("demo.namedUser: " + demo.namedUser); System.out.println("demo.allUsers: " + demo.allUsers); System.out.println("demo.qualifierUsers: " + demo.qualifierUsers); // 关闭应用上下文 applicationContext.close(); } } // 运行结果 demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.namedUser: User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.allUsers: [User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}] demo.qualifierUsers: [User{id=7, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}, User{id=8, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}]自定义分组注解, UserGroup
UserGroup
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.annotation.Qualifier; import java.lang.annotation.*; /** * 用户组注解: 扩展 {@link Qualifier @Qualifier} * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @Qualifier public @interface UserGroup { }QualifierAnnotationDependencylrjectionDemo
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import javax.jws.soap.SOAPBinding; import java.util.Collection; /** * {@link Qualifier} 注解依赖注入 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @see Qualifier * @since */ public class QualifierAnnotationDependencylrjectionDemo { @Autowired private User user; // super user -> primary = true @Autowired @Qualifier("user") private User namedUser; // 指定 Bean 名称 或 ID @Autowired // 只会获取不带Qualifier的Bean private Collection<User> allUsers; // 2 Bean -> super user, user @Autowired @Qualifier // 只会获取带Qualifier的Bean private Collection<User> qualifierUsers; // 2 Bean -> user1, user2, user3, user4 @Autowired @UserGroup private Collection<User> userGroupUsers; // 2 Bean -> user3, user4 @Bean @Qualifier // 进行逻辑分组 public User user1() { return createUser(7L); } @Bean @Qualifier // 进行逻辑分组 public User user2() { return createUser(8L); } @Bean @UserGroup // 进行逻辑分组 public User user3() { return createUser(9L); } @Bean @UserGroup // 进行逻辑分组 public User user4() { return createUser(10L); } public static User createUser(Long id) { User user = new User(); user.setId(id); return user; } public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(QualifierAnnotationDependencylrjectionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); QualifierAnnotationDependencylrjectionDemo demo = applicationContext.getBean(QualifierAnnotationDependencylrjectionDemo.class); System.out.println("demo.user: " + demo.user); System.out.println("demo.namedUser: " + demo.namedUser); System.out.println("demo.allUsers: " + demo.allUsers); System.out.println("demo.qualifierUsers: " + demo.qualifierUsers); System.out.println("demo.userGroupUsers: " + demo.userGroupUsers); // 关闭应用上下文 applicationContext.close(); } } // 运行结果 demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.namedUser: User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.allUsers: [User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}] demo.qualifierUsers: [User{id=7, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}, User{id=8, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}, User{id=9, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}, User{id=10, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}] demo.userGroupUsers: [User{id=9, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}, User{id=10, name='null', city=null, configFileLocation=null, workCities=null, lifeCities=null, map=null}] 
 -  
 -  
基于注解 @Qualifier 扩展限定
-  
自定义注解 - 如 Spring Cloud @LoadBalanced
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LKpYCUuC-1669797885497)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128105248225.png)]](https://img-blog.csdnimg.cn/df394e83232942958b488d6d90d21f4c.png)
 
 -  
 
14. 延迟依赖注入:如何实现延迟执行依赖注入?与延迟依赖查找是类似的吗?
-  
使用 API ObjectFactory 延迟注入
- 单一类型
 - 集合类型
 
 -  
使用 API ObjectProvider 延迟注入(推荐)
- 单一类型
 - 集合类型
 
 -  
LazyAnnotationDependencyInjectionDemo
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import javax.jws.soap.SOAPBinding; import java.util.Collection; /** * {@link ObjectProvider} 实现延迟依赖注入 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class LazyAnnotationDependencyInjectionDemo { @Autowired private User user; // 实时注入 @Autowired private ObjectProvider<User> userObjectProvider; // 延迟注入 @Autowired private ObjectFactory<Collection<User>> userObjectFactoryCollection; // 延迟注入 public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(LazyAnnotationDependencyInjectionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); LazyAnnotationDependencyInjectionDemo demo = applicationContext.getBean(LazyAnnotationDependencyInjectionDemo.class); // 输出 super user --> primary = true System.out.println("demo.user: " + demo.user); // 输出 super user System.out.println("demo.userObjectProvider: " + demo.userObjectProvider.getObject()); // ObjectProvider 继承 ObjectFactory // 输出 user, super user System.out.println("demo.userObjectFactory: " + demo.userObjectFactoryCollection.getObject()); // 输出 user, super user demo.userObjectProvider.forEach(System.out::println); // 关闭应用上下文 applicationContext.close(); } } // 运行结果 demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.userObjectProvider: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.userObjectFactory: [User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}] User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} 
15. 依赖处理过程:依赖处理时会发生什么?其中与依赖查找的差异在哪?
-  
基础知识
-  
入口 - DefaultListableBeanFactory#resolveDependency
AnnotationDependencyInjectionResolutionDemo 注入单个Bean
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import java.util.Collection; /** * 注解驱动的依赖注入处理过程 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AnnotationDependencyInjectionResolutionDemo { @Autowired // 依赖查找 (处理) private User user; // DependencyDescriptor -> // 必须 (required = true) // 实时注入 (eager = true) // 通过类型 (User.class) // 字段名称 ("user") // 是否首要 (primary = true) public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class); // 输出 super user --> primary = true System.out.println("demo.user: " + demo.user); // 关闭应用上下文 applicationContext.close(); } }![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4mZOIAOf-1669797885497)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128133614932.png)]](https://img-blog.csdnimg.cn/8fb5a61007ca4d8ebe41f21588819e08.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8hs0i9PS-1669797885497)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128134151416.png)]](https://img-blog.csdnimg.cn/49c2bc12ba9d4310994b6d2b12fa82fa.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wiZlFf97-1669797885498)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128134342366.png)]](https://img-blog.csdnimg.cn/677f54d5711e4c9dbaa964a1642cc351.png)

![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qwQVWBVM-1669797885498)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128134932540.png)]](https://img-blog.csdnimg.cn/5abaed6679d44c49b7a49e98d49b2e81.png)
因为我们xml定义了user和super user 所以这里有两个名称
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sQKW717F-1669797885498)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135019022.png)]](https://img-blog.csdnimg.cn/fc32289e78184238863f661ffc14dcf4.png)
它会加入两次
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IIm1dULL-1669797885499)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135313430.png)]](https://img-blog.csdnimg.cn/a76ea84d7b87406294dc655c3df5761b.png)
找到了两个
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-71MGIJb2-1669797885499)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135348382.png)]](https://img-blog.csdnimg.cn/422cba30731b48b8a5ac48c27f980fff.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T6aZ6g0Z-1669797885499)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135551329.png)]](https://img-blog.csdnimg.cn/ce413dd37fae4ec9a6f97c57c451ebe3.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1cyUIsNC-1669797885499)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135625674.png)]](https://img-blog.csdnimg.cn/11928e8ef59d4078af62f7952cbf27af.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4bzaDjvo-1669797885500)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135734720.png)]](https://img-blog.csdnimg.cn/e8c0cbe81a1345ad90c8122573c1c208.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KohpNKJR-1669797885500)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135822799.png)]](https://img-blog.csdnimg.cn/f54b708bb4774a6e854b81a20471917b.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kZBjGh1U-1669797885500)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135837587.png)]](https://img-blog.csdnimg.cn/df4135c5a6da42249ced29b82033fffa.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tclg0mfR-1669797885500)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135859058.png)]](https://img-blog.csdnimg.cn/e1a38fc97d224e5e9407e988e9068c69.png)
所以说判断是否为primary其实就是用的BeanDefinition里面的元信息
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EDE2Oqj3-1669797885501)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140105954.png)]](https://img-blog.csdnimg.cn/fe81d1d1e5874c6d9dd58def1f4868f7.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5cGVUV91-1669797885501)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140147105.png)]](https://img-blog.csdnimg.cn/c99b9511546543f5ad488d8da34a6b08.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R7cwj2Eg-1669797885501)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140344771.png)]](https://img-blog.csdnimg.cn/f7bcede9b2b44e59ac8f0bf5adf374ee.png)
注意: 这里拿到的super user是个class
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h2qdX1yY-1669797885501)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140532497.png)]](https://img-blog.csdnimg.cn/531b0ba1526549a7b18e798e104e355d.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m2dOCa7w-1669797885502)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140548684.png)]](https://img-blog.csdnimg.cn/de4e358c600b4a72b9ba575a59122300.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T6qdt5cM-1669797885502)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140612168.png)]](https://img-blog.csdnimg.cn/e4dec2e3ef6844bda78b6b6589c803b6.png)
AnnotationDependencyInjectionResolutionDemo 注入集合Bean
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Lazy; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import java.util.Collection; import java.util.Map; import java.util.Optional; /** * 注解驱动的依赖注入处理过程 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AnnotationDependencyInjectionResolutionDemo { @Autowired // 依赖查找 (处理) private User user; // DependencyDescriptor -> // 必须 (required = true) // 实时注入 (eager = true) // 通过类型 (User.class) // 字段名称 ("user") // 是否首要 (primary = true) @Autowired private Map<String, User> mapUser; public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class); // 输出 super user --> primary = true System.out.println("demo.user: " + demo.user); System.out.println("demo.mapUser: " + demo.mapUser); System.out.println("demo.optionalUser: " + demo.optionalUser.get()); System.out.println("demo.lazyUser: " + demo.lazyUser); // 关闭应用上下文 applicationContext.close(); } } // 运行结果 demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.mapUser: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}} demo.optionalUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Lazy; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import java.util.Collection; import java.util.Map; import java.util.Optional; /** * 注解驱动的依赖注入处理过程 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AnnotationDependencyInjectionResolutionDemo { @Autowired // 依赖查找 (处理) private User user; // DependencyDescriptor -> // 必须 (required = true) // 实时注入 (eager = true) // 通过类型 (User.class) // 字段名称 ("user") // 是否首要 (primary = true) @Autowired private Map<String, User> mapUser; @Autowired private Optional<User> optionalUser; public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class); // 输出 super user --> primary = true System.out.println("demo.user: " + demo.user); System.out.println("demo.mapUser: " + demo.mapUser); System.out.println("demo.optionalUser: " + demo.optionalUser.get()); System.out.println("demo.lazyUser: " + demo.lazyUser); // 关闭应用上下文 applicationContext.close(); } } // 运行结果 demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.mapUser: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}}其他同上唯一的就是这里事处理过个Bean
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5pUqs8iG-1669797885502)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128144850630.png)]](https://img-blog.csdnimg.cn/73d69378320e4e1bbf056872825b3830.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vy8UMM08-1669797885502)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128144725412.png)]](https://img-blog.csdnimg.cn/7544564f7fcc47b5b530dfb2d6a25dba.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4hkz0RSi-1669797885503)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128145011091.png)]](https://img-blog.csdnimg.cn/b0b514d681f64f45a4932e9a84a6208e.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jzNB9NCn-1669797885503)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128145125719.png)]](https://img-blog.csdnimg.cn/9c073115394c4c3cbda849f2cbff105a.png)
AnnotationDependencyInjectionResolutionDemo 注入Optional Bean
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Lazy; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import java.util.Collection; import java.util.Map; import java.util.Optional; /** * 注解驱动的依赖注入处理过程 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AnnotationDependencyInjectionResolutionDemo { @Autowired // 依赖查找 (处理) private User user; // DependencyDescriptor -> // 必须 (required = true) // 实时注入 (eager = true) // 通过类型 (User.class) // 字段名称 ("user") // 是否首要 (primary = true) @Autowired private Map<String, User> mapUser; @Autowired private Optional<User> optionalUser; public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class); // 输出 super user --> primary = true System.out.println("demo.user: " + demo.user); System.out.println("demo.mapUser: " + demo.mapUser); System.out.println("demo.optionalUser: " + demo.optionalUser.get()); System.out.println("demo.lazyUser: " + demo.lazyUser); // 关闭应用上下文 applicationContext.close(); } } // 运行结果 demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.mapUser: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}} demo.optionalUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EA60GzN0-1669797885503)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128170730478.png)]](https://img-blog.csdnimg.cn/08703e2487d14b968e412c62918d23b6.png)
AnnotationDependencyInjectionResolutionDemo 注入延迟 Bean
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Lazy; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import java.util.Collection; import java.util.Map; import java.util.Optional; /** * 注解驱动的依赖注入处理过程 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AnnotationDependencyInjectionResolutionDemo { @Autowired // 依赖查找 (处理) private User user; // DependencyDescriptor -> // 必须 (required = true) // 实时注入 (eager = true) // 通过类型 (User.class) // 字段名称 ("user") // 是否首要 (primary = true) @Autowired private Map<String, User> mapUser; @Autowired private Optional<User> optionalUser; @Autowired @Lazy // 延迟Bean private User lazyUser; public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class); // 输出 super user --> primary = true System.out.println("demo.user: " + demo.user); System.out.println("demo.mapUser: " + demo.mapUser); System.out.println("demo.optionalUser: " + demo.optionalUser.get()); System.out.println("demo.lazyUser: " + demo.lazyUser); // 关闭应用上下文 applicationContext.close(); } } // 运行结果 demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.mapUser: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}} demo.optionalUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.lazyUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B3WXIlRq-1669797885503)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128170913324.png)]](https://img-blog.csdnimg.cn/c48e9e4a621741969f63e6f9c3df0c0f.png)
 -  
依赖描述符 - DependencyDescriptor
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iQScfAZJ-1669797885503)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128114505496.png)]](https://img-blog.csdnimg.cn/e15aa2b0ec884c12a1a9033770299449.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Coe4DPru-1669797885504)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128131218321.png)]](https://img-blog.csdnimg.cn/8cae337c9f094af3bff79c852f02a9ca.png)
declaringClass: 当前声明注入, 注入描述, 换而言之它是一个被注入的容器, 那么这个容器就称为声明的这个类
methodName: 方法名称可以为空, (方法注入)
parameterTypes: 方法参数, 构造器参数来操作(构造器注入)
parameterIndex: 参数索引它的顺序从0开始
fieldName: 字段名(字段注入)
required: 可以理解为Autowired注解里面的required
eager: 可以理解为Lazy注解里面的value
nestingLevel: 嵌套层次这里主要指的事@Autowired也有可能放在你的嵌套类里面去
containingClass: 包含类
resolvableType: 泛型类型
typeDescriptor: 类型描述
方法注入, 字段注入, 构造器注入, 是可选的如果三个都是空它就没没有注入的来源, 那这个显然是不对的
 -  
自定绑定候选对象处理器 - AutowireCandidateResolver
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nHO9QNyF-1669797885504)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128114354781.png)]](https://img-blog.csdnimg.cn/06c2d52f70dd43998eb22b74372dfccc.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HvfGMXsr-1669797885504)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128114424300.png)]](https://img-blog.csdnimg.cn/0a39cdcb8eed429e9831c5773eb0d43e.png)
多个Bean是用的Set去重的方式, 所以是没有顺序可言的
总结
1、DefaultListableBeanFactory#resolveDependency 判断是否懒加载,懒加载直接返回CGLIB代理对象; 2、doResolveDependency 开始进行依赖注入; 3、resolveMultipleBeans 判断注入的对象是否是集合类型(Stream,Collection,Array,Map) ,是的话直接return ; 4、findAutowireCandidates 根据类型查找所有匹配到的bean,返回一个Map对象; 5、determineAutowireCandidate 选取唯一bean名称,如果有多个bean,即返回@Primary修饰的; 6、通过BeanFactory#getBean返回结果 
 -  
 
16. @Autowired注入:@Autowired注入的规则和原理有哪些?
-  
@Autowired 注入规则
- 非静态字段
 - 非静态方法
 - 构造器
 
 -  
@Autowired 注入过程
- 元信息解析
 - 依赖查找
 - 依赖注入(字段、方法)
 
package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import java.util.Collection; import java.util.Map; import java.util.Optional; /** * 注解驱动的依赖注入处理过程 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ @Configuration public class AnnotationDependencyInjectionResolutionDemo { @Autowired // 依赖查找 (处理) private User user; // DependencyDescriptor -> // 必须 (required = true) // 实时注入 (eager = true) // 通过类型 (User.class) // 字段名称 ("user") // 是否首要 (primary = true) // @Autowired // private Map<String, User> mapUser; // // @Autowired // private Optional<User> optionalUser; // // @Autowired // @Lazy // 延迟Bean // private User lazyUser; public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class); // 输出 super user --> primary = true System.out.println("demo.user: " + demo.user); // System.out.println("demo.mapUser: " + demo.mapUser); // System.out.println("demo.optionalUser: " + demo.optionalUser.get()); // System.out.println("demo.lazyUser: " + demo.lazyUser); // 关闭应用上下文 applicationContext.close(); } }

![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-znJCsFwt-1669799159681)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129185624440.png)]](https://img-blog.csdnimg.cn/0fe7b88cda1342339b96ce81e12613f5.png)
注意: 有CommonAnnotationBeanPostProcessor它会先执行CommonAnnotationBeanPostProcessor, 后执行AutowiredAnnotationBeanPostProcessor, 通过这个applyMergedBeanDefinitionPostProcessors方法循环就能看出, 想调整顺序自己修改order值
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Ks6ziOI-1669799159681)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129185731130.png)]](https://img-blog.csdnimg.cn/40a35ab86dfc4f769d9e78a881e01f42.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KFxReRvB-1669799159681)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190005684.png)]](https://img-blog.csdnimg.cn/738fd2581d9b4cb0a6556b7bb99ffcee.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PfBWvejD-1669799159681)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129182716395.png)]](https://img-blog.csdnimg.cn/d2d6426a58164a8d8c68099f7d30cc1b.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ta4CknCa-1669799159681)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190223321.png)]](https://img-blog.csdnimg.cn/da8239bfde7645a5a9dcb3c93c5f428d.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oTIGO91M-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190245185.png)]](https://img-blog.csdnimg.cn/733ae401dc3940f3aaccd23247dd1cf9.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jr4LdIMi-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129191855129.png)]](https://img-blog.csdnimg.cn/907a769db20c4221a385cfeb872a3d31.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aFxmThYw-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190540160.png)]](https://img-blog.csdnimg.cn/0a1c3655560e4627a3ae1f6b156b16a7.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AOA7UEsZ-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190933041.png)]](https://img-blog.csdnimg.cn/fe416acfd2dc4a32945f821df210be96.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s41cAu7d-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190952366.png)]](https://img-blog.csdnimg.cn/fdb62a45f5404baab967c51784fd46c2.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SEInoP4m-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129191149729.png)]](https://img-blog.csdnimg.cn/03785f84e0b54fe9a8a9a5fb83f91ad3.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o8goofIN-1669799159683)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129191303375.png)]](https://img-blog.csdnimg.cn/8107efcef2c24f40ac22a5e5607c942d.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oPbX9eN7-1669799159683)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129164438070.png)]](https://img-blog.csdnimg.cn/fa7cd490d55e4ebb9b5619339e9c3c86.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sPXo8mHg-1669799159683)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129191410051.png)]](https://img-blog.csdnimg.cn/e36695a4380945a3879b3f46989f709d.png)
剩下跟15一样过程了
总结:
先是找元信息然后进行注入:主要流程:AbstractAutowireCapableBeanFactory#createBean()-->doCreateBean() 1.调用applyMergedBeanDefinitionPostProcessors -> postProcessMergedBeanDefinition -> findAutowiringMetadata中找到该类中注解为Autowired、Value、Inject的字段、方法等 2.调用populateBean -> postProcessProperties,先调用findAutowiringMetadata找到待注入的元信息(比如user),然后调用metadata的inject方法,底层调用的是AutowiredFieldElement和AutowiredMethodElement的inject方法, 2.1 构造DependencyDescriptor(比如user) 2.2 调用beanFactory.resolveDependency获取待注入的bean(比如user),这里又是一轮的createBean(比如superUser不存在,则会创建) 2.3 获取后进行反射注入:field.set(bean, value) 
15-16连体总结:
在 AbstractApplicationContext#refresh#finishBeanFactoryInitialization 方法中,初始化所有还未初始化的 Bean(不是抽象、单例模式、不是懒加载方式)
通过 DefaultListableBeanFactory#preInstantiateSingletons 方法进行初始化,会通过 AbstractBeanFactory#getBean(beanName) 方法对每个 Bean 进行初始化
Bean 初始化的过程比较繁琐,大致过程如下:
1. 先找到对应的 BeanDefinition 对象,然后会走到 AbstractAutowireCapableBeanFactory#createBean 方法,**进行实例化**、**填充属性值**、调用 Bean 的**初始化方法**
2. 在填充属性值的过程,默认根据类型进行注入,那么在 AbstractAutowireCapableBeanFactory#autowireByType 的方法中会调用 DefaultListableBeanFactory#resolveDependency 方法进行注入,最后还是会通过 AbstractBeanFactory#getBean(beanName) 方法获取到需要注入的 Bean 对象
3. 在填充属性值的时候也会通过 AutowiredAnnotationBeanPostProcessor 注入属性值,该注入增强器会对 @Autowired 或者 @Value 注解标注的属性进行注入,也是通过 DefaultListableBeanFactory#resolveDependency 方法进行注入。具体过程可看 AutowiredAnnotationBeanPostProcessor 的私有内部类 AutowiredFieldElement#inject 方法
 
17. JSR-330 @Inject注入:@Inject与@Autowired的注入原理有怎样的联系?
-  
@Inject 注入过程
-  
如果 JSR-330 存在于 ClassPath 中,复用 AutowiredAnnotationBeanPostProcessor 实现
<!-- JSR 330 API --> <dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency>package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import javax.inject.Inject; import java.util.Collection; import java.util.Map; import java.util.Optional; /** * 注解驱动的依赖注入处理过程 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ @Configuration public class AnnotationDependencyInjectionResolutionDemo { @Autowired // 依赖查找 (处理) private User user; // DependencyDescriptor -> // 必须 (required = true) // 实时注入 (eager = true) // 通过类型 (User.class) // 字段名称 ("user") // 是否首要 (primary = true) // @Autowired // private Map<String, User> mapUser; // // @Autowired // private Optional<User> optionalUser; // // @Autowired // @Lazy // 延迟Bean // private User lazyUser; @Inject private User injectUser; public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class); // 输出 super user --> primary = true System.out.println("demo.user: " + demo.user); System.out.println("demo.injectUser: " + demo.injectUser); // System.out.println("demo.mapUser: " + demo.mapUser); // System.out.println("demo.optionalUser: " + demo.optionalUser.get()); // System.out.println("demo.lazyUser: " + demo.lazyUser); // 关闭应用上下文 applicationContext.close(); } } // 运行结果 demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.injectUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} -  
实现原理跟15-16一样
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VV9s27u2-1669797885505)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130112913241.png)]](https://img-blog.csdnimg.cn/b77aae80fc1b4e5bb3cc68ee9afc581c.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ujjWTy8q-1669797885505)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130112949260.png)]](https://img-blog.csdnimg.cn/98e71b1ea2434f768f22043400a14b0e.png)
遍历来查询装饰的注解, 注意它是有顺序的集合, 所以会根据添加的注解顺序来进行操作
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h5MlcLxc-1669797885505)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130113024410.png)]](https://img-blog.csdnimg.cn/ba5ac857ebf9481e815e6076c872e59f.png)
 
 -  
 
18. Java通用注解注入原理:Spring是如何实现@Resource和@EJB等注解注入的?
-  
CommonAnnotationBeanPostProcessor
- 注入注解 
    
- javax.xml.ws.WebServiceRef
 - javax.ejb.EJB
 - javax.annotation.Resource
 
 - 生命周期注解 
    
- javax.annotation.PostConstruct
 - javax.annotation.PreDestroy
 
 
其实CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor差不多, 只不过CommonAnnotationBeanPostProcessor多了一个生命周期, CommonAnnotationBeanPostProcessor倒数第4位, AutowiredAnnotationBeanPostProcessor倒数第三位, 所以CommonAnnotationBeanPostProcessor先执行后执行AutowiredAnnotationBeanPostProcessor
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eu02lqVb-1669797885505)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130133215467.png)]](https://img-blog.csdnimg.cn/4aef62a69dcf45e1a501bcf766c21d68.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AjZKwu6G-1669797885505)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130133232480.png)]](https://img-blog.csdnimg.cn/4d87639f0e0643f6b79f186669b090bc.png)
CommonAnnotationBeanPostProcessor倒数第4位, AutowiredAnnotationBeanPostProcessor倒数第三位, 所以CommonAnnotationBeanPostProcessor先执行后执行AutowiredAnnotationBeanPostProcessor
可以自定义order或者@Order
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mADi8Xi1-1669797885506)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130133813927.png)]](https://img-blog.csdnimg.cn/ad03c3b0de064ecf9d18eaba6b33aef4.png)
它多个用的LifecycleMetadata元信息
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2dpHOPxg-1669797885506)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130143609594.png)]](https://img-blog.csdnimg.cn/f545732ed0e843dea9ea948ec1a57ef4.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yeMKQhlC-1669797885506)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130143629469.png)]](https://img-blog.csdnimg.cn/54a0e50f81e14a16bde4b504f1cc0c6b.png)
多了个初始化方法和销毁方法, 对应的就是PostConstruct/PreDestroy
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cz6737Wf-1669797885506)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130143646227.png)]](https://img-blog.csdnimg.cn/26b0273a4f1d49dbaba0e1b2e1793a7e.png)
找元信息
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9UtPGVAL-1669797885506)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130144304810.png)]](https://img-blog.csdnimg.cn/2e3d839c91cf469cb65831c7d50db08a.png)
跟AutowiredAnnotationBeanPostProcessor那个查询一样, 主要看buildResourceMetadata
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A1YREu1K-1669797885507)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130144604421.png)]](https://img-blog.csdnimg.cn/97cc847417434b25813fedd39cbac212.png)
@Resource也是不能放在含static的字段/方法的, 递归去查找元信息
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0py2VeOP-1669797885507)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130144625910.png)]](https://img-blog.csdnimg.cn/8384b277c05545ceb4d063a2a2793540.png)
PostConstruct/PreDestroy在哪里执行的
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LmFGDX7A-1669797885507)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130145125313.png)]](https://img-blog.csdnimg.cn/fa0ab9b9c9d1445a9ae894ac64ccb5b4.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bB8O5V1v-1669797885507)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130145155269.png)]](https://img-blog.csdnimg.cn/9fe46dec45024c01a2aab630c3be44bc.png)
它会去构建LifecycleElement的method方法, 所以生命周期的两个注解PostConstruct/PreDestroy只允许注入到方法上面
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZLsCCzhn-1669797885507)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130145433854.png)]](https://img-blog.csdnimg.cn/3953d590331f469eaa07e6b34755c46c.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9NQ9zCvZ-1669797885508)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130145518648.png)]](https://img-blog.csdnimg.cn/a1e5a71485e54f8fb14559f7a45a8741.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yZ0xgHOq-1669797885508)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151347314.png)]](https://img-blog.csdnimg.cn/c4477fe066344c2b93304291fd8fb46e.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fEqUBUev-1669797885508)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151408515.png)]](https://img-blog.csdnimg.cn/830a9eb2989744faa089799770b92352.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MmxhvDNm-1669797885508)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151501110.png)]](https://img-blog.csdnimg.cn/9d62b5e6a4c14902adc677046f3d7210.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9sUAdBeX-1669797885508)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151522385.png)]](https://img-blog.csdnimg.cn/7611808f37f246dbb5b61ee8a65739b3.png)
递归先父类,后子类的PostConstruct/PreDestroy
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O7r0RgHG-1669797885509)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151539975.png)]](https://img-blog.csdnimg.cn/2e611d377c1a4c9287d6bc48ae8c000f.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1jTRbC8v-1669797885509)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151602824.png)]](https://img-blog.csdnimg.cn/736e524df0b14116abb0d9ec7e521ecc.png)
生命周期回调方法
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Vxw5eam-1669797885509)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151947979.png)]](https://img-blog.csdnimg.cn/42e4f54b82e64b189fa810e65f10b378.png)
 - 注入注解 
    
 
19. 自定义依赖注入注解:如何最简化实现自定义依赖注入注解?
-  
基于 AutowiredAnnotationBeanPostProcessor 实现
package org.xiaoge.thinking.in.spring.ioc.dependency.injection.annotation; import org.springframework.beans.factory.annotation.Autowired; import java.lang.annotation.*; /** * 自定义注入使用(@Autowired 元注解) * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ @Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Autowired public @interface MyAutowired { /** * Declares whether the annotated dependency is required. * <p>Defaults to {@code true}. */ boolean required() default true; }package org.xiaoge.thinking.in.spring.ioc.dependency.injection.annotation; import java.lang.annotation.*; /** * 自定义依赖注入注解 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ @Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface InjectedUser { }package org.xiaoge.thinking.in.spring.ioc.dependency.injection; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.xiaoge.thinking.in.spring.ioc.dependency.injection.annotation.InjectedUser; import org.xiaoge.thinking.in.spring.ioc.dependency.injection.annotation.MyAutowired; import org.xiaoge.thinking.in.spring.ioc.overview.domain.User; import javax.inject.Inject; import java.util.Collection; import java.util.Map; import java.util.Optional; import static org.springframework.context.annotation.AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME; /** * 注解驱动的依赖注入处理过程 * * @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a> * @since */ public class AnnotationDependencyInjectionResolutionDemo { @Autowired // 依赖查找 (处理) private User user; // DependencyDescriptor -> // 必须 (required = true) // 实时注入 (eager = true) // 通过类型 (User.class) // 字段名称 ("user") // 是否首要 (primary = true) @Autowired private Map<String, User> mapUser; @Autowired private Optional<User> optionalUser; @Autowired @Lazy // 延迟Bean private User lazyUser; @Inject private User injectUser; @MyAutowired private User myAutowiredUser; @InjectedUser private User injectedUser; /** * * 核心是Bean名称是AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME, 因为它只会注入一次 * 只注入我自己的注解, 其他注解全部失效, 想之前的也生效用setAutowiredAnnotationTypes吧其他注解也加载进来 * @return */ // @Bean(name = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME) // public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() { // AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor(); // autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectedUser.class); // return autowiredAnnotationBeanPostProcessor; // } /** * 兼容老的api, 新老都生效 让容器里面存在两个(AutowiredAnnotationBeanPostProcessor) * @return */ @Bean public static AutowiredAnnotationBeanPostProcessor beanPostProcessor2() { AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor(); autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectedUser.class); return autowiredAnnotationBeanPostProcessor; } /** * 无效 * @return */ // @Bean // public AutowiredAnnotationBeanPostProcessor beanPostProcessor2() { // AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor(); // autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectedUser.class); // return autowiredAnnotationBeanPostProcessor; // } public static void main(String[] args) { // 创建 ApplicationContext 容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // 注册 Configuration Class 配置类 applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext); xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml"); // 启动应用上下文 applicationContext.refresh(); AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class); // 输出 super user --> primary = true System.out.println("demo.user: " + demo.user); System.out.println("demo.injectUser: " + demo.injectUser); System.out.println("demo.mapUser: " + demo.mapUser); System.out.println("demo.optionalUser: " + demo.optionalUser); System.out.println("demo.lazyUser: " + demo.lazyUser); System.out.println("demo.myAutowiredUser: " + demo.myAutowiredUser);// AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME System.out.println("demo.injectedUser: " + demo.injectedUser);// AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME // 关闭应用上下文 applicationContext.close(); } } // 运行结果 demo.user: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.injectUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.mapUser: {user=User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}, superUser=SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}} demo.optionalUser: Optional[SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}] demo.lazyUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.myAutowiredUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}} demo.injectedUser: SuperUser{address='武汉'} User{id=1, name='xiaoge', city=WUHAN, configFileLocation=class path resource [META-INF/dependency-lookup-context.xml], workCities=[WUHAN, HANGZHOU], lifeCities=[WUHAN, BEIJING], map={one=1, two=2}}就是因为它所以只有自定义注解生效了, 原有注解失效, 因为它只会注入一次, 而加了static的优先

总结:
上下文refresh后,会调用registerBeanPostProcessors注册各beanPostProcessors。此时demo所在的类并没有初始化为bean。 但是如果要拿到自定义的AutowiredAnnotationBeanPostProcessor,就必须拿到demo的bean后调用beanPostProcessor来拿到这个PostProcessor bean。这就必然导致整个demo配置类先实例化初始化,也就导致@InjectUser注入的bean还没有被AutowiredAnnotationBeanPostProcessor解析,就注入进来了,也就是null。如果加上static,那么就不需要先拿到demo的bean,可以直接调用类方法获取这个AutowiredAnnotationBeanPostProcessor。那么就会导致先拿到processor,后拿到demo的bean。这样demo在初始化的时候,就会正常解析自定义@InjectUser。所以对于同时存在bean的定义和bean的注入的配置类,顺序很容易弄错。 -  
自定义实现
- 生命周期处理 
    
- InstantiationAwareBeanPostProcessor
 - MergedBeanDefinitionPostProcessor
 
 - 元数据 
    
- InjectedElement
 - InjectionMetadata
 
 
 - 生命周期处理 
    
 
20. 面试题精选
- 有多少种依赖注入的方式? 
  
- 构造器注入
 - Setter 注入
 - 字段注入
 - 方法注入
 - 接口回调注入
 
 - 你偏好构造器注入还是 Setter 注入? 
  
- 答:两种依赖注入的方式均可使用,如果是必须依赖的话,那么推荐使用构造器注入,Setter 注入用于可选依赖。
 
 



![[附源码]Python计算机毕业设计Django的物品交换平台](https://img-blog.csdnimg.cn/ae690f09ab264cde9e5b384c81ea8331.png)















