• Spring IoC依赖注入-6


    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
        • 1
    • 优点

      • Autowiring can significantly reduce the need to specify properties or constructor arguments.

        Autowiring 可以有效减少我们一些属性或构造器参数的一个设定
        
        • 1
      • Autowiring can update a configuration as your objects evolve.

        自动绑定能更新配置, 就当你的对象正在被逐渐升级或逐渐形成的时候
        
        • 1

    3. 自动绑定(Autowiring)模式:各种自动绑定模式的使用场景是什么?

    • Autowiring modes

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2uOAbmv3-1669797885493)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124162056276.png)]

      参考枚举: org.springframework. beans.factory.annotation.Autowire

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jp8xrNLT-1669797885494)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124164442428.png)]

      为什么没有构造器模式, 因为构造器模式是一种特殊的BY_TYPE

    4. 自动绑定(Autowiring)限制和不足:如何理解和挖掘官方文档中深层次的含义?

    5. Setter方法依赖注入:Setter注入的原理是什么?

    • 实现方法

      • 手动模式

        • XML资源配置元信息

          • dependency-lookup-context.xml

            
            <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 id="user" class="org.xiaoge.thinking.in.spring.ioc.overview.domain.User">
                    <property name="id" value="1" />
                    <property name="name" value="xiaoge"/>
                bean>
            
                
                <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
                    <property name="targetBeanName" value="user" />
                bean>
            
                
                <bean id="superUser" class="org.xiaoge.thinking.in.spring.ioc.overview.domain.SuperUser" parent="user" primary="true">
                    <property name="address" value="武汉" />
                bean>
            
            beans>
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
          • dependency-setter-injection.xml

            
            <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"/>
            
                
                <bean class="org.xiaoge.thinking.in.spring.ioc.dependency.injection.UserHolder">
                    <property name="user" ref="user">property>
                bean>
            
            beans>
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
          • 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 Zhang Xiao
             * @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 +
                            '}';
                }
            }
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33
            • 34
            • 35
            • 36
          • 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 Zhang Xiao
             * @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'}}
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
        • .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 Zhang Xiao
             * @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'}}
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33
            • 34
            • 35
            • 36
            • 37
            • 38
            • 39
            • 40
            • 41
            • 42
            • 43
            • 44
            • 45
            • 46
            • 47
            • 48
            • 49
            • 50
            • 51
            • 52
            • 53
            • 54
        • 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 Zhang Xiao
             * @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'}}
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33
            • 34
            • 35
            • 36
            • 37
            • 38
            • 39
            • 40
            • 41
            • 42
            • 43
            • 44
            • 45
            • 46
            • 47
            • 48
            • 49
            • 50
            • 51
            • 52
            • 53
            • 54
            • 55
            • 56
            • 57
            • 58
      • 自动模式

        • byName

          • autowiring-dependency-setter-injection.xml

            
            <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"/>
            
                
                <bean class="org.xiaoge.thinking.in.spring.ioc.dependency.injection.UserHolder"
                      autowire="byName">
            
                bean>
            
            beans>
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
          • 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 Zhang Xiao
             * @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'}}
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33
        • byType

          • autowiring-dependency-setter-injection.xml

            
            <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"/>
            
                
                <bean class="org.xiaoge.thinking.in.spring.ioc.dependency.injection.UserHolder"
                      autowire="byType">
            
                bean>
            
            beans>
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
          • 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 Zhang Xiao
             * @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"
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33
            • 34
            • 35

    6. 构造器依赖注入:官方为什么推荐使用构造器注入?

    • 实现方法

      • 手动模式

        • XML 资源配置元信

          • dependency-constructor-injection.xml

            
            <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"/>
            
                
                <bean class="org.xiaoge.thinking.in.spring.ioc.dependency.injection.UserHolder">
                    <constructor-arg name="user" ref="superUser">constructor-arg>
                bean>
            
            beans>
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
          • XmlDependencyConstructorInjectionDemo.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 资源的依赖 Constructor 注入 示例
             *
             * @author Zhang Xiao
             * @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'}}
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
        • 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 Zhang Xiao
             * @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'}}
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33
            • 34
            • 35
            • 36
            • 37
            • 38
            • 39
            • 40
            • 41
            • 42
            • 43
            • 44
            • 45
            • 46
            • 47
            • 48
            • 49
            • 50
            • 51
            • 52
        • 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 Zhang Xiao
             * @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'}}
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33
            • 34
            • 35
            • 36
            • 37
            • 38
            • 39
            • 40
            • 41
            • 42
            • 43
            • 44
            • 45
            • 46
            • 47
            • 48
            • 49
            • 50
            • 51
            • 52
            • 53
            • 54
            • 55
      • 自动模式

        • constructor

          • autowiring-dependency-constructor-injection.xml

            
            <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"/>
            
                
                <bean class="org.xiaoge.thinking.in.spring.ioc.dependency.injection.UserHolder"
                      autowire="constructor">
            
                bean>
            
            beans>
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
          • 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 Zhang Xiao
             * @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'}}
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33

    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 Zhang Xiao
             * @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
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33
            • 34
            • 35
            • 36
            • 37
            • 38
            • 39
            • 40
            • 41
            • 42
            • 43
            • 44
            • 45
            • 46
            • 47
            • 48
            • 49
            • 50
            • 51
            • 52
            • 53
            • 54
            • 55
            • 56
            • 57
            • 58
            • 59
            • 60
            • 61
            • 62
            • 63
            • 64
            • 65
            • 66
            • 67

            所以这里指的字段注入, 是指的实例字段/对象字段

    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 Zhang Xiao
             * @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
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33
            • 34
            • 35
            • 36
            • 37
            • 38
            • 39
            • 40
            • 41
            • 42
            • 43
            • 44
            • 45
            • 46
            • 47
            • 48
            • 49
            • 50
            • 51
            • 52
            • 53
            • 54
            • 55
            • 56
            • 57
            • 58
            • 59
            • 60
            • 61
            • 62
            • 63
            • 64
            • 65
            • 66
            • 67
            • 68
            • 69
            • 70
            • 71
            • 72
            • 73
            • 74
            • 75
            • 76
            • 77

            注意: 方法注入只关注方法参数类型(不关注方法名称, 方法名称可以随便写), 它会去spring上下文中去找对应类型的对象赋值给方法的参数

    9. 接口回调注入:回调注入的使用场景和限制有哪些?

    • Aware 系列接口回调

      • 自动模式

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LDRF49VT-1669797885494)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125152547024.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nysGzMrK-1669797885494)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125152604985.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 Zhang Xiao
         * @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
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59

    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)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b74KpryM-1669797885495)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164429336.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WAFGUlCe-1669797885495)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164444863.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZjjZPcCU-1669797885496)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164517057.png)]

        resource为什么打印出来会有class path resource因为它是掉的ClassPathResource的toString方法

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A0BFgnvq-1669797885496)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164713707.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dRkNSeuA-1669797885496)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164724118.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DMWWKScN-1669797885496)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221125164750366.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;
              }
          }
          
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78
          • 79
          • 80
          • 81
          • 82
          • 83
          • 84
          • 85
          • 86
          • 87
          • 88
          • 89
          • 90
          • 91
          • 92
          • 93
          • 94
          • 95
          • 96
          • 97
          • 98
          • 99
          • 100
          • 101
          • 102
          • 103
          • 104
          • 105
          • 106
          • 107
          • 108
          • 109
        • dependency-lookup-context.xml

          
          <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 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">
                      <list>
                          <value>WUHANvalue>
                          <value>BEIJINGvalue>
                      list>
                  property>
                  <property name="map">
                      <map>
                         <entry key="one" value="1" />
                         <entry key="two" value="2" />
                      map>
                  property>
              bean>
          
              
              <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
                  <property name="targetBeanName" value="user" />
              bean>
          
              
              <bean id="superUser" class="org.xiaoge.thinking.in.spring.ioc.overview.domain.SuperUser" parent="user" primary="true">
                  <property name="address" value="武汉" />
              bean>
          
          beans>
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
        • 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 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}}}
          
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78
          • 79
          • 80
          • 81
          • 82
          • 83
          • 84
          • 85
          • 86
          • 87
          • 88
          • 89
          • 90
          • 91
          • 92
          • 93
          • 94
          • 95
          • 96
          • 97
          • 98
          • 99
          • 100
          • 101
          • 102
          • 103
          • 104
          • 105
          • 106
          • 107
          • 108
          • 109

    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 Zhang Xiao
         * @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}}
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
      • 通过分组限定

        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 Zhang Xiao
         * @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}]
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68
        • 69
        • 70
        • 71
        • 72
        • 73
        • 74
        • 75
        • 76
        • 77
        • 78
        • 79
        • 80
        • 81
        • 82
        • 83

        自定义分组注解, 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 Zhang Xiao
         * @since
         */
        @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
        @Retention(RetentionPolicy.RUNTIME)
        @Inherited
        @Documented
        @Qualifier
        public @interface UserGroup {
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19

        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 Zhang Xiao
         * @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}]
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68
        • 69
        • 70
        • 71
        • 72
        • 73
        • 74
        • 75
        • 76
        • 77
        • 78
        • 79
        • 80
        • 81
        • 82
        • 83
        • 84
        • 85
        • 86
        • 87
        • 88
        • 89
        • 90
        • 91
        • 92
        • 93
        • 94
        • 95
        • 96
        • 97
        • 98
        • 99
        • 100
        • 101
        • 102
        • 103
        • 104
    • 基于注解 @Qualifier 扩展限定

      • 自定义注解 - 如 Spring Cloud @LoadBalanced

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LKpYCUuC-1669797885497)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128105248225.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 Zhang Xiao
       * @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}}
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67

    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 Zhang Xiao
         * @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();
            }
        
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4mZOIAOf-1669797885497)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128133614932.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8hs0i9PS-1669797885497)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128134151416.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wiZlFf97-1669797885498)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128134342366.png)]

        C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128134701951.png

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qwQVWBVM-1669797885498)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128134932540.png)]

        因为我们xml定义了user和super user 所以这里有两个名称

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sQKW717F-1669797885498)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135019022.png)]

        它会加入两次

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IIm1dULL-1669797885499)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135313430.png)]

        找到了两个

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-71MGIJb2-1669797885499)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135348382.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T6aZ6g0Z-1669797885499)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135551329.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1cyUIsNC-1669797885499)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135625674.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4bzaDjvo-1669797885500)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135734720.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KohpNKJR-1669797885500)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135822799.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kZBjGh1U-1669797885500)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135837587.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tclg0mfR-1669797885500)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128135859058.png)]

        所以说判断是否为primary其实就是用的BeanDefinition里面的元信息

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EDE2Oqj3-1669797885501)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140105954.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5cGVUV91-1669797885501)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140147105.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R7cwj2Eg-1669797885501)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140344771.png)]

        注意: 这里拿到的super user是个class

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h2qdX1yY-1669797885501)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140532497.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m2dOCa7w-1669797885502)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140548684.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T6qdt5cM-1669797885502)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128140612168.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 Zhang Xiao
         * @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 Zhang Xiao
         * @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}}}
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68
        • 69
        • 70
        • 71
        • 72
        • 73
        • 74
        • 75
        • 76
        • 77
        • 78
        • 79
        • 80
        • 81
        • 82
        • 83
        • 84
        • 85
        • 86
        • 87
        • 88
        • 89
        • 90
        • 91
        • 92
        • 93
        • 94
        • 95
        • 96
        • 97
        • 98
        • 99
        • 100
        • 101
        • 102
        • 103
        • 104
        • 105
        • 106
        • 107
        • 108
        • 109
        • 110
        • 111
        • 112
        • 113
        • 114
        • 115
        • 116
        • 117
        • 118
        • 119
        • 120
        • 121
        • 122
        • 123
        • 124
        • 125
        • 126
        • 127
        • 128
        • 129
        • 130
        • 131

        其他同上唯一的就是这里事处理过个Bean

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5pUqs8iG-1669797885502)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128144850630.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vy8UMM08-1669797885502)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128144725412.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4hkz0RSi-1669797885503)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128145011091.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jzNB9NCn-1669797885503)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128145125719.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 Zhang Xiao
         * @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}}
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EA60GzN0-1669797885503)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128170730478.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 Zhang Xiao
         * @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}}
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68
        • 69
        • 70
        • 71
        • 72
        • 73

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B3WXIlRq-1669797885503)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128170913324.png)]

      • 依赖描述符 - DependencyDescriptor

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iQScfAZJ-1669797885503)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128114505496.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Coe4DPru-1669797885504)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128131218321.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)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HvfGMXsr-1669797885504)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221128114424300.png)]

        多个Bean是用的Set去重的方式, 所以是没有顺序可言的

        总结

        1DefaultListableBeanFactory#resolveDependency  判断是否懒加载,懒加载直接返回CGLIB代理对象;
        2、doResolveDependency		开始进行依赖注入;
        3、resolveMultipleBeans			判断注入的对象是否是集合类型(Stream,Collection,Array,Map) ,是的话直接return4、findAutowireCandidates		根据类型查找所有匹配到的bean,返回一个Map对象;
        5、determineAutowireCandidate	选取唯一bean名称,如果有多个bean,即返回@Primary修饰的;
        6、通过BeanFactory#getBean返回结果
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6

    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 Zhang Xiao
       * @since
       */
      @Configuration
      public class AnnotationDependencyInjectionResolutionDemo {
      
          @Autowired // 依赖查找 (处理)
          private User user;  // DependencyDescriptor ->
                              // 必须 (required = true)
                              // 实时注入 (eager = true)
                              // 通过类型 (User.class)
                              // 字段名称 ("user")
                              // 是否首要 (primary = true)
      
      //    @Autowired
      //    private Map mapUser;
      //
      //    @Autowired
      //    private Optional 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();
          }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68

      在这里插入图片描述

      在这里插入图片描述

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-znJCsFwt-1669799159681)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129185624440.png)]

      注意: 有CommonAnnotationBeanPostProcessor它会先执行CommonAnnotationBeanPostProcessor, 后执行AutowiredAnnotationBeanPostProcessor, 通过这个applyMergedBeanDefinitionPostProcessors方法循环就能看出, 想调整顺序自己修改order值

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Ks6ziOI-1669799159681)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129185731130.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KFxReRvB-1669799159681)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190005684.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PfBWvejD-1669799159681)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129182716395.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ta4CknCa-1669799159681)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190223321.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oTIGO91M-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190245185.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jr4LdIMi-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129191855129.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aFxmThYw-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190540160.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AOA7UEsZ-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190933041.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s41cAu7d-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129190952366.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SEInoP4m-1669799159682)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129191149729.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o8goofIN-1669799159683)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129191303375.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oPbX9eN7-1669799159683)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129164438070.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sPXo8mHg-1669799159683)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221129191410051.png)]

      剩下跟15一样过程了

      总结:

      先是找元信息然后进行注入:主要流程:AbstractAutowireCapableBeanFactory#createBean()-->doCreateBean()
      1.调用applyMergedBeanDefinitionPostProcessors -> postProcessMergedBeanDefinition -> findAutowiringMetadata中找到该类中注解为AutowiredValueInject的字段、方法等
      2.调用populateBean -> postProcessProperties,先调用findAutowiringMetadata找到待注入的元信息(比如user),然后调用metadata的inject方法,底层调用的是AutowiredFieldElementAutowiredMethodElement的inject方法,
      2.1 构造DependencyDescriptor(比如user)
      2.2 调用beanFactory.resolveDependency获取待注入的bean(比如user),这里又是一轮的createBean(比如superUser不存在,则会创建)
      2.3 获取后进行反射注入:field.set(bean, value)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    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 方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    17. JSR-330 @Inject注入:@Inject与@Autowired的注入原理有怎样的联系?

    • @Inject 注入过程

      • 如果 JSR-330 存在于 ClassPath 中,复用 AutowiredAnnotationBeanPostProcessor 实现

        
        <dependency>
            <groupId>javax.injectgroupId>
            <artifactId>javax.injectartifactId>
            <version>1version>
        dependency>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        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 Zhang Xiao
         * @since
         */
        @Configuration
        public class AnnotationDependencyInjectionResolutionDemo {
        
            @Autowired // 依赖查找 (处理)
            private User user;  // DependencyDescriptor ->
                                // 必须 (required = true)
                                // 实时注入 (eager = true)
                                // 通过类型 (User.class)
                                // 字段名称 ("user")
                                // 是否首要 (primary = true)
        
        //    @Autowired
        //    private Map mapUser;
        //
        //    @Autowired
        //    private Optional 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}}
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68
        • 69
        • 70
        • 71
        • 72
        • 73
        • 74
        • 75
        • 76
        • 77
        • 78
      • 实现原理跟15-16一样

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VV9s27u2-1669797885505)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130112913241.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ujjWTy8q-1669797885505)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130112949260.png)]

        遍历来查询装饰的注解, 注意它是有顺序的集合, 所以会根据添加的注解顺序来进行操作

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h5MlcLxc-1669797885505)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130113024410.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)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AjZKwu6G-1669797885505)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130133232480.png)]

      CommonAnnotationBeanPostProcessor倒数第4位, AutowiredAnnotationBeanPostProcessor倒数第三位, 所以CommonAnnotationBeanPostProcessor先执行后执行AutowiredAnnotationBeanPostProcessor

      可以自定义order或者@Order

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mADi8Xi1-1669797885506)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130133813927.png)]

      它多个用的LifecycleMetadata元信息

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2dpHOPxg-1669797885506)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130143609594.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yeMKQhlC-1669797885506)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130143629469.png)]

      多了个初始化方法和销毁方法, 对应的就是PostConstruct/PreDestroy

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cz6737Wf-1669797885506)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130143646227.png)]

      找元信息

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9UtPGVAL-1669797885506)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130144304810.png)]

      跟AutowiredAnnotationBeanPostProcessor那个查询一样, 主要看buildResourceMetadata

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A1YREu1K-1669797885507)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130144604421.png)]

      @Resource也是不能放在含static的字段/方法的, 递归去查找元信息

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0py2VeOP-1669797885507)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130144625910.png)]

      PostConstruct/PreDestroy在哪里执行的

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LmFGDX7A-1669797885507)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130145125313.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bB8O5V1v-1669797885507)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130145155269.png)]

      它会去构建LifecycleElement的method方法, 所以生命周期的两个注解PostConstruct/PreDestroy只允许注入到方法上面

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZLsCCzhn-1669797885507)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130145433854.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9NQ9zCvZ-1669797885508)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130145518648.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yZ0xgHOq-1669797885508)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151347314.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fEqUBUev-1669797885508)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151408515.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MmxhvDNm-1669797885508)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151501110.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9sUAdBeX-1669797885508)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151522385.png)]

      递归先父类,后子类的PostConstruct/PreDestroy

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O7r0RgHG-1669797885509)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151539975.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1jTRbC8v-1669797885509)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151602824.png)]

      生命周期回调方法

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Vxw5eam-1669797885509)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221130151947979.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 Zhang Xiao
       * @since
       */
      @Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Autowired
      public @interface MyAutowired {
      
          /**
           * Declares whether the annotated dependency is required.
           * 

      Defaults to {@code true}. */ boolean required() default true; }

      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      package org.xiaoge.thinking.in.spring.ioc.dependency.injection.annotation;
      
      import java.lang.annotation.*;
      
      /**
       * 自定义依赖注入注解
       *
       * @author Zhang Xiao
       * @since
       */
      @Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      public @interface InjectedUser {
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      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 Zhang Xiao
       * @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}}
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100
      • 101
      • 102
      • 103
      • 104
      • 105
      • 106
      • 107
      • 108
      • 109
      • 110
      • 111
      • 112
      • 113
      • 114
      • 115
      • 116
      • 117
      • 118
      • 119
      • 120
      • 121
      • 122
      • 123
      • 124
      • 125
      • 126
      • 127
      • 128
      • 129
      • 130
      • 131
      • 132
      • 133

      就是因为它所以只有自定义注解生效了, 原有注解失效, 因为它只会注入一次, 而加了static的优先

      image-20221130162553984

      总结:

      上下文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的注入的配置类,顺序很容易弄错。
      
      • 1
      • 2
    • 自定义实现

      • 生命周期处理
        • InstantiationAwareBeanPostProcessor
        • MergedBeanDefinitionPostProcessor
      • 元数据
        • InjectedElement
        • InjectionMetadata

    20. 面试题精选

    • 有多少种依赖注入的方式?
      • 构造器注入
      • Setter 注入
      • 字段注入
      • 方法注入
      • 接口回调注入
    • 你偏好构造器注入还是 Setter 注入?
      • 答:两种依赖注入的方式均可使用,如果是必须依赖的话,那么推荐使用构造器注入,Setter 注入用于可选依赖。
  • 相关阅读:
    项目研发,有哪些好用的免费脑图工具软件
    制造企业使用APS计划排产需要的条件
    基因组的Phasing原理
    BS-GX-018 基于SSM实现在校学生考试系统
    【Gan教程 】 什么是变分自动编码器VAE?
    iLogtail 社区版使用入门 - 采集 MySQL Binlog
    Docker网桥模式ping不通宿主机
    20231014后台面经总结
    (最新版2022版)剑指offer之排序题解
    Linux中的磁盘
  • 原文地址:https://blog.csdn.net/zsx1314lovezyf/article/details/128118049