• 万字博客带你全面剖析Spring的依赖注入


    1.写在前面

    前面的博客我们已经写了Spring的依赖查找,这篇博客我们来了解写Spring的依赖注入

    2.依赖注入的模式和类型

    手动模式 - 配置或者编程的方式, 提前安排注入规则

    • XML 资源配置元信息
    • Java 注解配置元信息
    • API 配置元信息

    自动模式 - 实现方提供依赖自动关联的方式, 按照內建的注入规则

    • Autowiring( 自动绑定)

    依赖注入的类型

    在这里插入图片描述

    3.自动绑定( 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 之间的关系。 您可以让 Spring 通过检查 ApplicationContext 的内容自动为您的 bean 解析协作者(其他 bean)。

    优点

    • Autowiring can significantly reduce the need to specify properties or constructor arguments.(自动装配可以显着减少指定属性或构造函数参数的需要。)
    • Autowiring can update a configuration as your objects evolve.(随着对象的发展,自动装配可以更新配置。)

    4.自动绑定( Autowiring) 模式

    在这里插入图片描述

    5.自动绑定( Autowiring) 限制和不足

    官方说明

    6.Setter 方法注入

    实现方法

    • 手动模式
      • XML 资源配置元信息
      • Java 注解配置元信息
      • API 配置元信息
    • 自动模式
      • byName
      • byType

    下面我们来展示各种代码,具体的如下:

    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.learn.spring.dependency.injection.UserHolder">
            <property name="user" ref="superUser"/>
        bean>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    package org.learn.spring.dependency.injection;
    
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    
    // 基于 xml 的setter依赖注入的示例
    public class XmlDependencySetterInjectionDemo {
    
        public static void main(String[] args) {
            DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-setter-injection.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 创建依赖查找并且创建Bean
            UserHolder userHolder = beanFactory.getBean(UserHolder.class);
            System.out.println(userHolder);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Java 注解配置元信息

    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.ioc.overview.domain.User;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    
    import java.util.Map;
    
    // 基于 Annotation 的setter依赖注入的示例
    public class AnnotationDependencySetterInjectionDemo {
    
        public static void main(String[] args) {
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类
            applicationContext.register(AnnotationDependencySetterInjectionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 创建依赖查找并且创建Bean
            UserHolder userHolder = applicationContext.getBean(UserHolder.class);
            System.out.println(userHolder);
    
            // 显示的关闭spring应用上下文
            applicationContext.close();
        }
    
        @Bean
        public UserHolder userHolder(User user){
            UserHolder userHolder = new UserHolder();
            userHolder.setUser(user);
            return userHolder;
        }
    }
    
    • 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

    API 配置元信息

    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.ioc.overview.domain.User;
    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;
    
    // 基于 API 的setter依赖注入的示例
    public class ApiDependencySetterInjectionDemo {
    
        public static void main(String[] args) {
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
    
            // 生成UserHolder 的BeanDefinition
            BeanDefinition userHolderBeanDefinition = createUserHolderBeanDefinition();
    
            // 注册UserHolder 的BeanDefinition
            applicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 创建依赖查找并且创建Bean
            UserHolder userHolder = applicationContext.getBean(UserHolder.class);
            System.out.println(userHolder);
    
            // 显示的关闭spring应用上下文
            applicationContext.close();
        }
    
        // 为UserHolder生成BeanDefinition
        private static BeanDefinition createUserHolderBeanDefinition() {
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
            beanDefinitionBuilder.addPropertyReference("user", "superUser");
            return beanDefinitionBuilder.getBeanDefinition();
        }
    
    }
    
    
    • 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

    byName

    
    <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.learn.spring.dependency.injection.UserHolder" autowire="byName"/>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package org.learn.spring.dependency.injection;
    
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    
    // byName AutoWring 依赖 setter方法注入示例
    public class AutoWringByNameDependencySetterInjectionDemo {
    
        public static void main(String[] args) {
            DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
            String xmlResourcePath = "classpath:/META-INF/autowring-dependency-setter-injection.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 创建依赖查找并且创建Bean
            UserHolder userHolder = beanFactory.getBean(UserHolder.class);
            System.out.println(userHolder);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    byType

    
    <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.learn.spring.dependency.injection.UserHolder" autowire="byType"/>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package org.learn.spring.dependency.injection;
    
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    
    // byName AutoWring 依赖 setter方法注入示例
    public class AutoWringByNameDependencySetterInjectionDemo {
    
        public static void main(String[] args) {
            DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
            String xmlResourcePath = "classpath:/META-INF/autowring-dependency-setter-injection.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 创建依赖查找并且创建Bean
            UserHolder userHolder = beanFactory.getBean(UserHolder.class);
            System.out.println(userHolder);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    7.构造器注入

    实现方法

    • 手动模式
      • XML 资源配置元信息
      • Java 注解配置元信息
      • API 配置元信息
    • 自动模式
      • constructor

    下面来展示示例代码

    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.learn.spring.dependency.injection.UserHolder">
            <constructor-arg name="user" ref="superUser"/>
        bean>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    package org.learn.spring.dependency.injection;
    
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    
    // 基于 xml 的Constructor依赖注入的示例
    public class XmlDependencyConstructorInjectionDemo {
    
        public static void main(String[] args) {
            DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-constructor-injection.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 创建依赖查找并且创建Bean
            UserHolder userHolder = beanFactory.getBean(UserHolder.class);
            System.out.println(userHolder);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    Java 注解配置元信息

    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.ioc.overview.domain.User;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    
    // 基于 Annotation 的Constructor依赖注入的示例
    public class AnnotationDependencyConstructorInjectionDemo {
    
        public static void main(String[] args) {
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类
            applicationContext.register(AnnotationDependencyConstructorInjectionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 创建依赖查找并且创建Bean
            UserHolder userHolder = applicationContext.getBean(UserHolder.class);
            System.out.println(userHolder);
    
            // 显示的关闭spring应用上下文
            applicationContext.close();
        }
    
        @Bean
        public UserHolder userHolder(User user){
            return new UserHolder(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

    API 配置元信息

    package org.learn.spring.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依赖注入的示例
    public class ApiDependencyConstructorInjectionDemo {
    
        public static void main(String[] args) {
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
    
            // 生成UserHolder 的BeanDefinition
            BeanDefinition userHolderBeanDefinition = createUserHolderBeanDefinition();
    
            // 注册UserHolder 的BeanDefinition
            applicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 创建依赖查找并且创建Bean
            UserHolder userHolder = applicationContext.getBean(UserHolder.class);
            System.out.println(userHolder);
    
            // 显示的关闭spring应用上下文
            applicationContext.close();
        }
    
        // 为UserHolder生成BeanDefinition
        private static BeanDefinition createUserHolderBeanDefinition() {
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
            beanDefinitionBuilder.addConstructorArgReference("superUser");
            return beanDefinitionBuilder.getBeanDefinition();
        }
    
    }
    
    • 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

    constructor

    
    <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.learn.spring.dependency.injection.UserHolder" autowire="constructor"/>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package org.learn.spring.dependency.injection;
    
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    
    // constructor AutoWring 依赖 constructor方法注入示例
    public class AutoWringConstructorDependencyConstructorInjectionDemo {
    
        public static void main(String[] args) {
            DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
            String xmlResourcePath = "classpath:/META-INF/autowring-dependency-constructor-injection.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 创建依赖查找并且创建Bean
            UserHolder userHolder = beanFactory.getBean(UserHolder.class);
            System.out.println(userHolder);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    8.字段注入

    实现方法

    • 手动模式
    • Java 注解配置元信息
      • @Autowired
      • @Resource
      • @Inject( 可选)

    具体的代码如下:

    @Autowired

    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.ioc.overview.domain.User;
    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.Bean;
    
    // 基于 Annotation 的Field依赖注入的示例
    public class AnnotationDependencyFieldInjectionDemo {
    
        @Autowired // @Autowired 会忽略静态字段
        private UserHolder userHolder;
    
        public static void main(String[] args) {
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(AnnotationDependencyFieldInjectionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 AnnotationDependencyFieldInjectionDemo Bean
            AnnotationDependencyFieldInjectionDemo demo = applicationContext.getBean(AnnotationDependencyFieldInjectionDemo.class);
    
            // 通过@Autowired字段关联
            UserHolder userHolder = demo.userHolder;
            System.out.println(userHolder);
    
            // 显示的关闭spring应用上下文
            applicationContext.close();
        }
    
        @Bean
        public UserHolder userHolder(User user){
            return new UserHolder(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

    @Resource

    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.ioc.overview.domain.User;
    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.Bean;
    
    import javax.annotation.Resource;
    
    // 基于 Annotation 的Field依赖注入的示例
    public class AnnotationDependencyFieldInjectionDemo {
    
        @Autowired // @Autowired 会忽略静态字段
        private UserHolder userHolder;
    
        @Resource
        private UserHolder userHolder2;
    
        public static void main(String[] args) {
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(AnnotationDependencyFieldInjectionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 AnnotationDependencyFieldInjectionDemo Bean
            AnnotationDependencyFieldInjectionDemo demo = applicationContext.getBean(AnnotationDependencyFieldInjectionDemo.class);
    
            // 通过@Autowired字段关联
            UserHolder userHolder = demo.userHolder;
            System.out.println(userHolder);
    
            // 通过@Resource字段关联
            UserHolder userHolder2 = demo.userHolder2;
            System.out.println(userHolder2);
    
            // 显示的关闭spring应用上下文
            applicationContext.close();
        }
    
        @Bean
        public UserHolder userHolder(User user){
            return new UserHolder(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

    9.方法注入

    实现方法

    • 手动模式
      • Java 注解配置元信息
        • @Autowired
        • @Resource
        • @Inject( 可选)
        • @Bean

    具体的代码如下:

    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.ioc.overview.domain.User;
    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.Bean;
    
    import javax.annotation.Resource;
    
    // 基于 Annotation 的Method依赖注入的示例
    public class AnnotationDependencyMethodInjectionDemo {
    
        private UserHolder userHolder;
    
        private UserHolder userHolder2;
    
        @Autowired
        public void init1(UserHolder userHolder){
            this.userHolder = userHolder;
        }
    
        @Resource
        public void init2(UserHolder userHolder2){
            this.userHolder2 = userHolder2;
        }
    
        public static void main(String[] args) {
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(AnnotationDependencyMethodInjectionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 AnnotationDependencyFieldInjectionDemo Bean
            AnnotationDependencyMethodInjectionDemo demo = applicationContext.getBean(AnnotationDependencyMethodInjectionDemo.class);
    
            // 通过@Autowired字段关联
            UserHolder userHolder = demo.userHolder;
            System.out.println(userHolder);
    
            // 通过@Resource字段关联
            UserHolder userHolder2 = demo.userHolder2;
            System.out.println(userHolder2);
    
            System.out.println(userHolder == userHolder2);
    
            // 显示的关闭spring应用上下文
            applicationContext.close();
        }
    
        @Bean
        public UserHolder userHolder(User user){
            return new UserHolder(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

    10.接口回调注入

    Aware 系列接口回调

    自动模式

    在这里插入图片描述

    在这里插入图片描述

    具体的代码如下:

    package org.learn.spring.dependency.injection;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    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;
    
    // 基于 Aware 的接口回调依赖注入的示例
    public class AwareInterfaceDependencyInjectionDemo implements BeanFactoryAware, ApplicationContextAware {
    
        private static BeanFactory beanFactory;
        private static ApplicationContext applicationContext;
    
        public static void main(String[] args) {
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            context.register(AwareInterfaceDependencyInjectionDemo.class);
    
            // 启动应用上下文
            context.refresh();
    
            System.out.println(beanFactory == context.getBeanFactory());
            System.out.println(applicationContext == context);
    
            // 显示的关闭spring应用上下文
            context.close();
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            AwareInterfaceDependencyInjectionDemo.beanFactory = beanFactory;
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            AwareInterfaceDependencyInjectionDemo.applicationContext = applicationContext;
        }
    }
    
    
    • 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

    11.依赖注入类型选择

    注入选型

    • 低依赖: 构造器注入
    • 多依赖: Setter 方法注入
    • 便利性: 字段注入
    • 声明类: 方法注入

    12.基础类型注入

    基础类型

    • 原生类型( 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 等

    具体的代码如下:

    
    <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.learn.spring.ioc.overview.domain.User">
            <property name="id" value="1"/>
            <property name="name" value="胡桃"/>
            <property name="city" value="HANGZHOU"/>
            <property name="configFileLocation" value="classpath:/META-INF/user-config.properties"/>
        bean>
    
        <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
            <property name="targetBeanName" value="user"/>
        bean>
    
        <bean id="superUser" class="org.learn.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
    package org.learn.spring.ioc.overview.domain;
    
    import org.learn.spring.ioc.overview.enums.City;
    import org.springframework.core.io.Resource;
    
    import java.util.Arrays;
    import java.util.List;
    
    // 用户类
    public class User {
    
        private Long id;
    
        private String name;
    
        private City city;
    
        private Resource configFileLocation;
    
        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 static User createUser(){
            User user = new User();
            user.setId(1L);
            user.setName("温蒂");
            return user;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", city=" + city +
                    ", configFileLocation=" + configFileLocation +
                    '}';
        }
    }
    
    
    • 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
    
    package org.learn.spring.ioc.overview.dependency.lookup;
    
    import org.learn.spring.ioc.overview.annotation.Super;
    import org.learn.spring.ioc.overview.domain.SuperUser;
    import org.learn.spring.ioc.overview.domain.User;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.ListableBeanFactory;
    import org.springframework.beans.factory.ObjectFactory;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.util.Map;
    
    // 依赖查找的示例
    public class DependencyLookupDemo {
    
        public static void main(String[] args) {
            // 配置XML 配置文件
            // 启动spring的应用上下文
            BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:META-INF/dependency-lookup-context.xml");
            // 1.按照名称查找
            lookupInRealTime(beanFactory);
            lookupInLazy(beanFactory);
    
            // 2.按照类型查找
            lookupByType(beanFactory);
            lookupCollectionByType(beanFactory);
    
            // 3.按照类型和名称查找
            lookupByNameAndType(beanFactory);
    
            // 4.通过注解查找对象
            lookupCollectionByAnnotation(beanFactory);
        }
    
        // 实时查找
        private static void lookupInRealTime(BeanFactory beanFactory) {
            User user = (User) beanFactory.getBean("user");
            System.out.println("实时查找:" + user);
        }
    
        // 延时查找
        private static void lookupInLazy(BeanFactory beanFactory) {
            ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
            User user = objectFactory.getObject();
            System.out.println("延时查找:" + user);
        }
    
        // 按照类型查找
        private static void lookupByType(BeanFactory beanFactory) {
            User user = beanFactory.getBean(User.class);
            System.out.println("按照类型查找单一对象:" + user);
        }
    
        // 按照类型查找集合
        private static void lookupCollectionByType(BeanFactory beanFactory) {
            if (beanFactory instanceof ListableBeanFactory) {
                ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
                Map<String, User> users = listableBeanFactory.getBeansOfType(User.class);
                System.out.println("按照类型查找到的所有的 User 集合对象:" + users);
            }
        }
    
        // 按照类型和名称
        private static void lookupByNameAndType(BeanFactory beanFactory) {
            User user = beanFactory.getBean("user", User.class);
            System.out.println("按照类型和名称查找:" + user);
        }
    
    
        // 按照注解查找集合对象
        private static void lookupCollectionByAnnotation(BeanFactory beanFactory) {
            if (beanFactory instanceof ListableBeanFactory) {
                ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
                Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);
                System.out.println("按照注解查找到的所有的标注@SuperUser User 集合对象:" + users);
            }
        }
    }
    
    
    • 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

    13.集合类型注入

    集合类型

    • 数组类型( Array) : 原生类型、 标量类型、 常规类型、 Spring 类型
    • 集合类型( Collection)
      • Collection: List、 Set( SortedSet、 NavigableSet、 EnumSet)
      • Map: Properties

    具体的代码如下:

    
    <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.learn.spring.ioc.overview.domain.User">
            <property name="id" value="1"/>
            <property name="name" value="胡桃"/>
            <property name="city" value="HANGZHOU"/>
            <property name="configFileLocation" value="classpath:/META-INF/user-config.properties"/>
            <property name="workCities" value="BEIJING,HANGZHOU"/>
            <property name="lifeCities">
                <list>
                    <value>BEIJINGvalue>
                    <value>HANGZHOUvalue>
                    <value>SHANGHAIvalue>
                list>
            property>
        bean>
    
        <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
            <property name="targetBeanName" value="user"/>
        bean>
    
        <bean id="superUser" class="org.learn.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
    package org.learn.spring.ioc.overview.domain;
    
    import org.learn.spring.ioc.overview.enums.City;
    import org.springframework.core.io.Resource;
    
    import java.util.Arrays;
    import java.util.List;
    
    // 用户类
    public class User {
    
        private Long id;
    
        private String name;
    
        private City city;
    
        private City[] workCities;
    
        private List<City> lifeCities;
    
        private Resource configFileLocation;
    
        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 static User createUser(){
            User user = new User();
            user.setId(1L);
            user.setName("温蒂");
            return user;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", city=" + city +
                    ", workCities=" + Arrays.toString(workCities) +
                    ", lifeCities=" + lifeCities +
                    ", configFileLocation=" + configFileLocation +
                    '}';
        }
    }
    
    
    • 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
    package org.learn.spring.ioc.overview.dependency.lookup;
    
    import org.learn.spring.ioc.overview.annotation.Super;
    import org.learn.spring.ioc.overview.domain.SuperUser;
    import org.learn.spring.ioc.overview.domain.User;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.ListableBeanFactory;
    import org.springframework.beans.factory.ObjectFactory;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.util.Map;
    
    // 依赖查找的示例
    public class DependencyLookupDemo {
    
        public static void main(String[] args) {
            // 配置XML 配置文件
            // 启动spring的应用上下文
            BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:META-INF/dependency-lookup-context.xml");
            // 1.按照名称查找
            lookupInRealTime(beanFactory);
            lookupInLazy(beanFactory);
    
            // 2.按照类型查找
            lookupByType(beanFactory);
            lookupCollectionByType(beanFactory);
    
            // 3.按照类型和名称查找
            lookupByNameAndType(beanFactory);
    
            // 4.通过注解查找对象
            lookupCollectionByAnnotation(beanFactory);
        }
    
        // 实时查找
        private static void lookupInRealTime(BeanFactory beanFactory) {
            User user = (User) beanFactory.getBean("user");
            System.out.println("实时查找:" + user);
        }
    
        // 延时查找
        private static void lookupInLazy(BeanFactory beanFactory) {
            ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
            User user = objectFactory.getObject();
            System.out.println("延时查找:" + user);
        }
    
        // 按照类型查找
        private static void lookupByType(BeanFactory beanFactory) {
            User user = beanFactory.getBean(User.class);
            System.out.println("按照类型查找单一对象:" + user);
        }
    
        // 按照类型查找集合
        private static void lookupCollectionByType(BeanFactory beanFactory) {
            if (beanFactory instanceof ListableBeanFactory) {
                ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
                Map<String, User> users = listableBeanFactory.getBeansOfType(User.class);
                System.out.println("按照类型查找到的所有的 User 集合对象:" + users);
            }
        }
    
        // 按照类型和名称
        private static void lookupByNameAndType(BeanFactory beanFactory) {
            User user = beanFactory.getBean("user", User.class);
            System.out.println("按照类型和名称查找:" + user);
        }
    
    
        // 按照注解查找集合对象
        private static void lookupCollectionByAnnotation(BeanFactory beanFactory) {
            if (beanFactory instanceof ListableBeanFactory) {
                ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
                Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);
                System.out.println("按照注解查找到的所有的标注@SuperUser User 集合对象:" + users);
            }
        }
    }
    
    
    • 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

    14.限定注入

    使用注解 @Qualifier 限定

    • 通过 Bean 名称限定
    • 通过分组限定

    基于注解 @Qualifier 扩展限定

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

    具体的代码如下:

    package org.learn.spring.dependency.injection.annotation;
    
    import org.springframework.beans.factory.annotation.Qualifier;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    // 用户组 注解 扩展 @Qualifier
    @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
    • 20
    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.dependency.injection.annotation.UserGroup;
    import org.learn.spring.ioc.overview.domain.User;
    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 java.util.Collection;
    
    // Qualifier 注解依赖注入
    public class QualifierAnnotationDependencyInjectionDemo {
    
        @Autowired
        private User user; // superUser -> primary
    
        @Autowired
        @Qualifier(value = "user") // 指定Bean 名称或者id注入
        private User nameUser;
    
        // 整体应用上下文存在4个 User类型的Bean:
        // superUser
        // user
        // user1 -> @Qualifier
        // user2 -> @Qualifier
    
        @Autowired
        private Collection<User> allUsers; // 2 Bean superUser + user
    
        @Autowired
        @Qualifier
        private Collection<User> qualifiedUsers; // 2 Bean = user1 + user2 -> 4 Bean = user1 + user2 + user3 + user4
    
        @Autowired
        @UserGroup
        private Collection<User> groupedUsers; // 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) {
    
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(QualifierAnnotationDependencyInjectionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 QualifierAnnotationDependencyInjectionDemo Bean
            QualifierAnnotationDependencyInjectionDemo demo = applicationContext.getBean(QualifierAnnotationDependencyInjectionDemo.class);
    
            // 期待输出superUser Bean
            System.out.println("demo.user = " + demo.user);
    
            // 期待输出user Bean
            System.out.println("demo.nameUser = " + demo.nameUser);
    
            // 期待输出2 Bean superUser + user
            System.out.println("demo.allUsers = " + demo.allUsers);
    
            // 期待输出2 Bean user1 user2
            System.out.println("demo.qualifiedUsers = " + demo.qualifiedUsers);
    
            // 期待输出2 Bean user3 user4
            System.out.println("demo.groupedUsers = " + demo.groupedUsers);
    
            // 显示的关闭spring应用上下文
            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
    • 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

    15.延迟依赖注入

    使用 API ObjectFactory 延迟注入

    • 单一类型
    • 集合类型

    使用 API ObjectProvider 延迟注入( 推荐)

    • 单一类型
    • 集合类型

    具体的代码如下:

    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.dependency.injection.annotation.UserGroup;
    import org.learn.spring.ioc.overview.domain.User;
    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.Qualifier;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    
    import java.util.Collection;
    import java.util.Set;
    
    // ObjectProvider 实现延迟依赖注入
    public class LazyAnnotationDependencyInjectionDemo {
    
        @Autowired
        private User user; // 实时注入
    
        @Autowired
        private ObjectProvider<User> userObjectProvider; // 延迟注入
    
        @Autowired
        private ObjectFactory<Set<User>> usersObjectFactory;
    
        public static void main(String[] args) {
    
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(LazyAnnotationDependencyInjectionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
            LazyAnnotationDependencyInjectionDemo demo = applicationContext.getBean(LazyAnnotationDependencyInjectionDemo.class);
    
            // 期待输出superUser Bean
            System.out.println("demo.user = " + demo.user);
    
            // 期待输出superUser Bean
            System.out.println("demo.userObjectProvider = " + demo.userObjectProvider.getObject()); // 继承ObjectFactory中的方法
    
            // 期待输出superUser User Bean
            System.out.println("demo.usersObjectFactory = " + demo.usersObjectFactory.getObject());
    
            demo.userObjectProvider.stream().forEach(System.out::println);
    
            // 显示的关闭spring应用上下文
            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

    16.依赖处理过程

    基础知识

    • 入口 - DefaultListableBeanFactory#resolveDependency
    • 依赖描述符 - DependencyDescriptor
    • 自定绑定候选对象处理器 - AutowireCandidateResolver

    先来简单的分析下对应的源码,具体的代码如下:

    /*
    *
    descriptor ——依赖项的描述符(字段/方法/构造函数) 
    requestingBeanName – 声明给定依赖项的 bean 的名称 
    autowiredBeanNames – 应该将所有自动装配 bean 的名称(用于解析给定的依赖项)添加到的集合 
    typeConverter – 类型转换器
    */
    @Override
    @Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
    			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
      descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
      if (Optional.class == descriptor.getDependencyType()) {
        return createOptionalDependency(descriptor, requestingBeanName);
      }
      else if (ObjectFactory.class == descriptor.getDependencyType() ||
               ObjectProvider.class == descriptor.getDependencyType()) {
        return new DependencyObjectProvider(descriptor, requestingBeanName);
      }
      else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
        return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
      }
      else {
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
          descriptor, requestingBeanName);
        if (result == null) {
          result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
      }
    }
    
    • 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

    我们先来看第一个参数DependencyDescriptor依赖的描述符,我们先打开对应的代码,先看对应的属性,具体的如下:

    public class DependencyDescriptor extends InjectionPoint implements Serializable {
    
      // 被注入的类、容器
    	private final Class<?> declaringClass;
    
      // 注入的方法的名称
    	@Nullable
    	private String methodName;
    
      // 注入的方法的参数类型
    	@Nullable
    	private Class<?>[] parameterTypes;
    
      // 注入的参数的索引
    	private int parameterIndex;
    
      // 注入的字段的名称
    	@Nullable
    	private String fieldName;
    
      // 是否是必须注入的 对应的@Autowired注解中的值
    	private final boolean required;
    
      // 对应的是@Lazy注解中的值
    	private final boolean eager;
    
      // 嵌入的层次
    	private int nestingLevel = 1;
    
      // 包含的类
    	@Nullable
    	private Class<?> containingClass;
    
      // 泛型的内容,后面的内容会讲
    	@Nullable
    	private transient volatile ResolvableType resolvableType;
    
      // 类型的描述
    	@Nullable
    	private transient volatile TypeDescriptor typeDescriptor;
      
    }
    
    • 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

    上面只是简单的分析了一下,比较模糊,下面我们通过一个简单的例子和debug的方式来帮助我们更深层次的理解,具体的例子如下:

    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.ioc.overview.domain.User;
    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 java.util.Set;
    
    // 注解实现延迟依赖注入处理过程
    public class AnnotationDependencyInjectionResolutionDemo {
    
        @Autowired // 依赖查找(处理)
        private User user;  // DependencyDescriptor ->
                            // 必须(required = true)
                            // (eager = true) 实时注入
                            // 通过类型(User.class)
                            // 字段名称("user")
                            // 是否是首要的(primary = true)
    
        public static void main(String[] args) {
    
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
            AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
    
            // 期待输出superUser Bean
            System.out.println("demo.user = " + demo.user);
    
    
            // 显示的关闭spring应用上下文
            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

    我们在DefaultListableBeanFactory#resolveDependency方法中加入对应的断点,然后Debug,就可以看到如下的截图,看看我们之前猜测的DependencyDescriptor是否是对的,具体的内容如下:

    在这里插入图片描述

    我们继续拿出之前的代码,具体的如下:

    @Override
    @Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
    			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
      // 这儿是字段注入,所以这个方法直接返回
      descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
      // descriptor.getDependencyType() 获取依赖的类型
      if (Optional.class == descriptor.getDependencyType()) {
        return createOptionalDependency(descriptor, requestingBeanName);
      }
      else if (ObjectFactory.class == descriptor.getDependencyType() ||
               ObjectProvider.class == descriptor.getDependencyType()) {
        return new DependencyObjectProvider(descriptor, requestingBeanName);
      }
      else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
        return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
      }
      else {
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
          descriptor, requestingBeanName);
        if (result == null) {
          result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
      }
    }
    
    • 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

    descriptor.getDependencyType()是获取依赖的类型,具体的内容如下:

    public Class<?> getDependencyType() {
      // 这里的field 是等于user
    		if (this.field != null) {
          // 这儿的层级是等于1,所以直接返回的user
    			if (this.nestingLevel > 1) {
    				Type type = this.field.getGenericType();
    				for (int i = 2; i <= this.nestingLevel; i++) {
    					if (type instanceof ParameterizedType) {
    						Type[] args = ((ParameterizedType) type).getActualTypeArguments();
    						type = args[args.length - 1];
    					}
    				}
    				if (type instanceof Class) {
    					return (Class<?>) type;
    				}
    				else if (type instanceof ParameterizedType) {
    					Type arg = ((ParameterizedType) type).getRawType();
    					if (arg instanceof Class) {
    						return (Class<?>) arg;
    					}
    				}
    				return Object.class;
    			}
    			else {
            // 直接返回user
    				return this.field.getType();
    			}
    		}
    		else {
    			return obtainMethodParameter().getNestedParameterType();
    		}
    	}
    
    • 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

    由于descriptor.getDependencyType()返回的是user类型,所以上面的resolveDependency的四个if判断的类型都是不满足的,直接走最后一个判断。代码如下:

    // 这个方法返回 null,后面再说
    Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
    if (result == null) {
      result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
    }
    return result;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后会直接调用doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);方法,具体的内容如下:

    @Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
                                      @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter 
                                      typeConverter) throws BeansException {
    
      // 只有多次嵌套的时候这儿才不会返回null
      InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
      try {
        // 快捷方式这儿也是没有的,返回的是null
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
          return shortcut;
        }
    
        // 这儿返回的是user类型
        Class<?> type = descriptor.getDependencyType();
        // 这儿返回的也是null,后面我们会讲
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
          if (value instanceof String) {
            String strVal = resolveEmbeddedValue((String) value);
            BeanDefinition bd = (beanName != null && containsBean(beanName) ?
                                 getMergedBeanDefinition(beanName) : null);
            value = evaluateBeanDefinitionString(strVal, bd);
          }
          TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
          try {
            return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
          }
          catch (UnsupportedOperationException ex) {
            // A custom TypeConverter which does not support TypeDescriptor resolution...
            return (descriptor.getField() != null ?
                    converter.convertIfNecessary(value, type, descriptor.getField()) :
                    converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
          }
        }
    
        // 直接跳到这儿执行
        // 这儿判断是否要注入的是多个bean,也是null
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
          return multipleBeans;
        }
    
        // 这儿方法中的beanName 等于的是 annotationDependencyInjectionResolutionDemo 也是被注入的beanName
        // type 是User.class
        // descriptor 是前面我们的DependencyDescriptor.class
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
          if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
          }
          return null;
        }
    
        String autowiredBeanName;
        Object instanceCandidate;
        
        if (matchingBeans.size() > 1) {
          autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
          if (autowiredBeanName == null) {
            if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
              return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
            }
            else {
              // In case of an optional Collection/Map, silently ignore a non-unique case:
              // possibly it was meant to be an empty collection of multiple regular beans
              // (before 4.3 in particular when we didn't even look for collection beans).
              return null;
            }
          }
          instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {
          // We have exactly one match.
          Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
          autowiredBeanName = entry.getKey();
          instanceCandidate = entry.getValue();
        }
    
        if (autowiredBeanNames != null) {
          autowiredBeanNames.add(autowiredBeanName);
        }
        if (instanceCandidate instanceof Class) {
          instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        if (result instanceof NullBean) {
          if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
          }
          result = null;
        }
        if (!ClassUtils.isAssignableValue(type, result)) {
          throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
        }
        return result;
      }
      finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
      }
    }
    
    • 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

    这儿我们需要了解是findAutowireCandidates(beanName, type, descriptor);方法,具体的内容如下:

    protected Map<String, Object> findAutowireCandidates(
      @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
      
      // 这儿是查找对应的beanName
      // this DefaultListableBeanFactory
      // requiredType User.class
      // true 查找的时候包含非单例的Bean
      // descriptor.isEager() 是否是非延迟加载
      // 这儿返回的beanName 应该是两个 一个 user 一个是superUser
      // 这儿是有序的,这儿的顺序就是你定义的顺序
      String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
        this, requiredType, true, descriptor.isEager());
      Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
      // 这儿代码我们不需要看,与我们的主流程没有任何关系,直接跳过
      for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
        Class<?> autowiringType = classObjectEntry.getKey();
        if (autowiringType.isAssignableFrom(requiredType)) {
          Object autowiringValue = classObjectEntry.getValue();
          autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
          if (requiredType.isInstance(autowiringValue)) {
            result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
            break;
          }
        }
      }
      // 直接跳到这个地方
     // 这儿遍历两次,将刚刚找出来的beanName,然后找到对应的Class 添加到reslut中去
      for (String candidate : candidateNames) {
        if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
          addCandidateEntry(result, candidate, descriptor, requiredType);
        }
      }
      // 这儿的长度是2,直接返回
      if (result.isEmpty()) {
        boolean multiple = indicatesMultipleBeans(requiredType);
        // Consider fallback matches if the first pass failed to find anything...
        DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
        for (String candidate : candidateNames) {
          if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
              (!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
            addCandidateEntry(result, candidate, descriptor, requiredType);
          }
        }
        if (result.isEmpty() && !multiple) {
          // Consider self references as a final pass...
          // but in the case of a dependency collection, not the very same bean itself.
          for (String candidate : candidateNames) {
            if (isSelfReference(beanName, candidate) &&
                (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
                isAutowireCandidate(candidate, fallbackDescriptor)) {
              addCandidateEntry(result, candidate, descriptor, requiredType);
            }
          }
        }
      }
      return result;
    }
    
    • 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

    上面的流程走完了,我们在回到原来的代码,具体的如下:

    @Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
                                      @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter 
                                      typeConverter) throws BeansException {
    
      // 只有多次嵌套的时候这儿才不会返回null
      InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
      try {
        // 快捷方式这儿也是没有的,返回的是null
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
          return shortcut;
        }
    
        // 这儿返回的是user类型
        Class<?> type = descriptor.getDependencyType();
        // 这儿返回的也是null,后面我们会讲
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
          if (value instanceof String) {
            String strVal = resolveEmbeddedValue((String) value);
            BeanDefinition bd = (beanName != null && containsBean(beanName) ?
                                 getMergedBeanDefinition(beanName) : null);
            value = evaluateBeanDefinitionString(strVal, bd);
          }
          TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
          try {
            return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
          }
          catch (UnsupportedOperationException ex) {
            // A custom TypeConverter which does not support TypeDescriptor resolution...
            return (descriptor.getField() != null ?
                    converter.convertIfNecessary(value, type, descriptor.getField()) :
                    converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
          }
        }
    
        // 直接跳到这儿执行
        // 这儿判断是否要注入的是多个bean,也是null
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
          return multipleBeans;
        }
    
        // 这儿方法中的beanName 等于的是 annotationDependencyInjectionResolutionDemo 也是被注入的beanName
        // type 是User.class
        // descriptor 是前面我们的DependencyDescriptor.class
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        // 这个map的长度是2,这个判断是不会进的,继续往下走
        if (matchingBeans.isEmpty()) {
          if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
          }
          return null;
        }
    
        String autowiredBeanName;
        Object instanceCandidate;
        
        // 会走到这儿
        if (matchingBeans.size() > 1) {
          // 这儿会找到首要的Bean,就是Primary
          autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
          if (autowiredBeanName == null) {
            if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
              return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
            }
            else {
              // In case of an optional Collection/Map, silently ignore a non-unique case:
              // possibly it was meant to be an empty collection of multiple regular beans
              // (before 4.3 in particular when we didn't even look for collection beans).
              return null;
            }
          }
          // 这儿找到了superUser
          instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {
          // We have exactly one match.
          Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
          autowiredBeanName = entry.getKey();
          instanceCandidate = entry.getValue();
        }
    
        // 添加到对应autowiredBeanNames 添加的内容是superUser
        if (autowiredBeanNames != null) {
          autowiredBeanNames.add(autowiredBeanName);
        }
        // superUser 直接getBean 这儿直接转成一个Bean对象
        if (instanceCandidate instanceof Class) {
          instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        if (result instanceof NullBean) {
          if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
          }
          result = null;
        }
        if (!ClassUtils.isAssignableValue(type, result)) {
          throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
        }
        // 最终返回了
        return result;
      }
      finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
      }
    }
    
    • 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

    上面的源码分析,是注入一个简单的,下面我们来分析下注入集合的。将原来的示例代码修改如下:

    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.ioc.overview.domain.User;
    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 java.util.Collection;
    import java.util.Map;
    import java.util.Set;
    
    // 注解实现延迟依赖注入处理过程
    public class AnnotationDependencyInjectionResolutionDemo {
    
        @Autowired // 依赖查找(处理)
        private User user;  // DependencyDescriptor ->
                            // 必须(required = true)
                            // (eager = true) 实时注入
                            // 通过类型(User.class)
                            // 字段名称("user")
                            // 是否是首要的(primary = true)
    
        @Autowired // 集合类型的依赖注入
        private Map<String, User> users; // user superUser
    
        public static void main(String[] args) {
    
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
            AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
    
            // 期待输出superUser Bean
            System.out.println("demo.user = " + demo.user);
    
    
            // 显示的关闭spring应用上下文
            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

    前面的代码都是一样的,我们直接看如下的代码:

    @Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
                                      @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter 
                                      typeConverter) throws BeansException {
    
      // 只有多次嵌套的时候这儿才不会返回null
      InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
      try {
        // 快捷方式这儿也是没有的,返回的是null
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
          return shortcut;
        }
    
        // 这儿返回的是user类型
        Class<?> type = descriptor.getDependencyType();
        // 这儿返回的也是null,后面我们会讲
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
          if (value instanceof String) {
            String strVal = resolveEmbeddedValue((String) value);
            BeanDefinition bd = (beanName != null && containsBean(beanName) ?
                                 getMergedBeanDefinition(beanName) : null);
            value = evaluateBeanDefinitionString(strVal, bd);
          }
          TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
          try {
            return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
          }
          catch (UnsupportedOperationException ex) {
            // A custom TypeConverter which does not support TypeDescriptor resolution...
            return (descriptor.getField() != null ?
                    converter.convertIfNecessary(value, type, descriptor.getField()) :
                    converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
          }
        }
    
        // 直接跳到这儿执行
        // 这儿判断是否要注入的是多个bean,我们先跳到这个方法中看对应的代码
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
          return multipleBeans;
        }
    
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
          if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
          }
          return null;
        }
    
        String autowiredBeanName;
        Object instanceCandidate;
        
        if (matchingBeans.size() > 1) {
          autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
          if (autowiredBeanName == null) {
            if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
              return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
            }
            else {
              // In case of an optional Collection/Map, silently ignore a non-unique case:
              // possibly it was meant to be an empty collection of multiple regular beans
              // (before 4.3 in particular when we didn't even look for collection beans).
              return null;
            }
          }
          instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {
          // We have exactly one match.
          Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
          autowiredBeanName = entry.getKey();
          instanceCandidate = entry.getValue();
        }
    
        if (autowiredBeanNames != null) {
          autowiredBeanNames.add(autowiredBeanName);
        }
       
        if (instanceCandidate instanceof Class) {
          instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        if (result instanceof NullBean) {
          if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
          }
          result = null;
        }
        if (!ClassUtils.isAssignableValue(type, result)) {
          throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
        }
        
        return result;
      }
      finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
      }
    }
    
    • 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

    这儿直接调用的resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);这个方法,具体的代码如下:

    	@Nullable
    	private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
    			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
    
        // 这儿的获取的类型是map
    		final Class<?> type = descriptor.getDependencyType();
    
        // 判断不满足 直接跳过
    		if (descriptor instanceof StreamDependencyDescriptor) {
    			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
    			if (autowiredBeanNames != null) {
    				autowiredBeanNames.addAll(matchingBeans.keySet());
    			}
    			Stream<Object> stream = matchingBeans.keySet().stream()
    					.map(name -> descriptor.resolveCandidate(name, type, this))
    					.filter(bean -> !(bean instanceof NullBean));
    			if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
    				stream = stream.sorted(adaptOrderComparator(matchingBeans));
    			}
    			return stream;
    		}
        
        // 判断不满足 直接跳过
    		else if (type.isArray()) {
    			Class<?> componentType = type.getComponentType();
    			ResolvableType resolvableType = descriptor.getResolvableType();
    			Class<?> resolvedArrayType = resolvableType.resolve(type);
    			if (resolvedArrayType != type) {
    				componentType = resolvableType.getComponentType().resolve();
    			}
    			if (componentType == null) {
    				return null;
    			}
    			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
    					new MultiElementDescriptor(descriptor));
    			if (matchingBeans.isEmpty()) {
    				return null;
    			}
    			if (autowiredBeanNames != null) {
    				autowiredBeanNames.addAll(matchingBeans.keySet());
    			}
    			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
    			Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
    			if (result instanceof Object[]) {
    				Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
    				if (comparator != null) {
    					Arrays.sort((Object[]) result, comparator);
    				}
    			}
    			return result;
    		}
        // 判断不满足 直接跳过
    		else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
    			Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
    			if (elementType == null) {
    				return null;
    			}
    			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
    					new MultiElementDescriptor(descriptor));
    			if (matchingBeans.isEmpty()) {
    				return null;
    			}
    			if (autowiredBeanNames != null) {
    				autowiredBeanNames.addAll(matchingBeans.keySet());
    			}
    			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
    			Object result = converter.convertIfNecessary(matchingBeans.values(), type);
    			if (result instanceof List) {
    				Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
    				if (comparator != null) {
    					((List<?>) result).sort(comparator);
    				}
    			}
    			return result;
    		}
        // 直接跳到这个地方
    		else if (Map.class == type) {
          // 获取Map的类型
    			ResolvableType mapType = descriptor.getResolvableType().asMap();
          // 获取 Map的key 的类型 String.class
    			Class<?> keyType = mapType.resolveGeneric(0);
          // 判断不成立 继续
    			if (String.class != keyType) {
    				return null;
    			}
          // 获取 Map的value的类型 User.class
    			Class<?> valueType = mapType.resolveGeneric(1);
          // 判断不成立 继续
    			if (valueType == null) {
    				return null;
    			}
          // 将这个value的类型调用前面我们讲过的方法 和前面的逻辑是一样的,进行查找,这个时候返回是user superUser
    			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
    					new MultiElementDescriptor(descriptor));
          // 这儿查找出来了,不会空,继续
    			if (matchingBeans.isEmpty()) {
    				return null;
    			}
          // 这儿也不是空,直接将对应beanName添加到autowiredBeanNames 返回
    			if (autowiredBeanNames != null) {
    				autowiredBeanNames.addAll(matchingBeans.keySet());
    			}
    			return matchingBeans;
    		}
    		else {
    			return 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
    • 105
    • 106
    • 107
    • 108

    由于这儿返回不是null,所以doResolveDependency()也不会走接下来的逻辑,直接返回,这样就找到了。

    还有OptionalObjectFactoryObjectProvider,Lazy的情况,我这儿就不讲了,感兴趣的可以去看看。需要注意的是如果是Lazy的话,返回的是代理的对象,只有在使用的时候,才会初始化。

    17.@Autowired 注入

    @Autowired 注入规则

    • 非静态字段
    • 非静态方法
    • 构造器

    @Autowired 注入过程

    • 元信息解析
    • 依赖查找
    • 依赖注入( 字段、 方法)

    前面的代码我们主要分析的是依赖的查找的过程,但是@Autowired 注入过程还有两个比较重要的过程,一个是元信息解析,还有一个是依赖的注入。这个时候我们需要通过idea的调用栈来得到这一部分的答案。主要调用的是AutowiredAnnotationBeanPostProcessor#AutowiredFieldElement#inject的方法,具体的代码如下:

    		@Override
    		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
          // 需要注入的filed
    			Field field = (Field) this.member;
    			Object value;
          // 默认是false,直接跳过
    			if (this.cached) {
    				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    			}
    			else {
            // 创建DependencyDescriptor 依赖描述
    				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
            // 设置包含的类 AnnotationDependencyInjectionResolutionDemo.class
    				desc.setContainingClass(bean.getClass());
            // 装配的beanName 后面会进行查找
    				Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
    				Assert.state(beanFactory != null, "No BeanFactory available");
            // 获取类型转换器
    				TypeConverter typeConverter = beanFactory.getTypeConverter();
    				try {
              // 依赖的查找,前面讲的
    					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    				}
    				catch (BeansException ex) {
    					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
    				}
            // 这儿是处理缓存,查找出来就缓存起来
    				synchronized (this) {
    					if (!this.cached) {
    						if (value != null || this.required) {
    							this.cachedFieldValue = desc;
    							registerDependentBeans(beanName, autowiredBeanNames);
    							if (autowiredBeanNames.size() == 1) {
    								String autowiredBeanName = autowiredBeanNames.iterator().next();
    								if (beanFactory.containsBean(autowiredBeanName) &&
    										beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
    									this.cachedFieldValue = new ShortcutDependencyDescriptor(
    											desc, autowiredBeanName, field.getType());
    								}
    							}
    						}
    						else {
    							this.cachedFieldValue = null;
    						}
    						this.cached = true;
    					}
    				}
    			}
          // 找到了,通过反射的方法创建对应的file,然后set进去。
    			if (value != null) {
    				ReflectionUtils.makeAccessible(field);
    				field.set(bean, value);
    			}
    		}
    
    • 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

    这个时候我们需要通过对应的调用栈继续往上查找,先看到的是org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition具体的代码如下:

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

    我们需要看findAutowiringMetadata(beanName, beanType, null);元数据的解析。代码的如下:

    	private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    		// Fall back to class name as cache key, for backwards compatibility with custom callers.
        // 获取的 缓存的key
    		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    		// Quick check on the concurrent map first, with minimal locking.
        // 从缓存中取值,第一次肯定为空
    		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    			synchronized (this.injectionMetadataCache) {
            // 再次从缓存中取值,还是为空
    				metadata = this.injectionMetadataCache.get(cacheKey);
    				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    					if (metadata != null) {
    						metadata.clear(pvs);
    					}
              // 构建元数据
    					metadata = buildAutowiringMetadata(clazz);
    					this.injectionMetadataCache.put(cacheKey, metadata);
    				}
    			}
    		}
    		return metadata;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
    			return InjectionMetadata.EMPTY;
    		}
    
    		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    		Class<?> targetClass = clazz;
    
    		do {
    			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
    
          // 通过递归的查找 @Autowired 的属性,直至查找Object.class
    			ReflectionUtils.doWithLocalFields(targetClass, field -> {
            // 查找对应的属性是否有 @Autowired 的注解
    				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
    				if (ann != null) {
              // 这儿我们也可以看出是不支持 static的属性
    					if (Modifier.isStatic(field.getModifiers())) {
    						if (logger.isInfoEnabled()) {
    							logger.info("Autowired annotation is not supported on static fields: " + field);
    						}
    						return;
    					}
              // 判断是否是required
    					boolean required = determineRequiredStatus(ann);
    					currElements.add(new AutowiredFieldElement(field, required));
    				}
    			});
    
          // 通过递归的查找 @Autowired 的方法,直至查找Object.class
    			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
    				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
    					return;
    				}
    				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
    				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
    					if (Modifier.isStatic(method.getModifiers())) {
    						if (logger.isInfoEnabled()) {
    							logger.info("Autowired annotation is not supported on static methods: " + method);
    						}
    						return;
    					}
    					if (method.getParameterCount() == 0) {
    						if (logger.isInfoEnabled()) {
    							logger.info("Autowired annotation should only be used on methods with parameters: " +
    									method);
    						}
    					}
    					boolean required = determineRequiredStatus(ann);
    					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
    					currElements.add(new AutowiredMethodElement(method, required, pd));
    				}
    			});
    
    			elements.addAll(0, currElements);
    			targetClass = targetClass.getSuperclass();
    		}
    		while (targetClass != null && targetClass != Object.class);
    
    		return InjectionMetadata.forElements(elements, clazz);
    	}
    
    • 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

    通过上面的分析,元信息解析是org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition,依赖查找,依赖注入( 字段、 方法)是org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties

    18.@Inject 注入

    @Inject 注入过程

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

    我们可以看下AutowiredAnnotationBeanPostProcessor,这个类可以处理的注解是@Value、@Autowired、@Inject,具体的如下:

    	public AutowiredAnnotationBeanPostProcessor() {
    		this.autowiredAnnotationTypes.add(Autowired.class);
    		this.autowiredAnnotationTypes.add(Value.class);
    		try {
    			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
    					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
    			logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
    		}
    		catch (ClassNotFoundException ex) {
    			// JSR-330 API not available - simply skip.
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    那么是怎么去针对出现多个对应的注解查找呢?findAutowiredAnnotation(AccessibleObject ao)我们需要看的方法如下:

    	@Nullable
    	private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
    		MergedAnnotations annotations = MergedAnnotations.from(ao);
        // autowiredAnnotationTypes 是LinkedHashSet是有序的,这儿的插入的属性是Autowired Value Inject
        // 所以如果一个字段或者方法上出现多个这个注解优先处理Autowired注解
    		for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
    			MergedAnnotation<?> annotation = annotations.get(type);
    			if (annotation.isPresent()) {
    				return annotation;
    			}
    		}
    		return null;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    这个时候我们简单的演示一个例子。具体的如下:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <parent>
            <artifactId>learn-spring-coreartifactId>
            <groupId>org.learn.springgroupId>
            <version>1.0-SNAPSHOTversion>
        parent>
        <modelVersion>4.0.0modelVersion>
        <artifactId>dependency-injectionartifactId>
    
        <dependencies>
            <dependency>
                <groupId>${groupId}groupId>
                <artifactId>ioc-container-overviewartifactId>
                <version>${version}version>
                <scope>compilescope>
            dependency>
    
            
            <dependency>
                <groupId>javax.injectgroupId>
                <artifactId>javax.injectartifactId>
                <version>1version>
            dependency>
        dependencies>
    project>
    
    
    • 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
    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.ioc.overview.domain.User;
    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 javax.inject.Inject;
    import java.util.Collection;
    import java.util.Map;
    import java.util.Set;
    
    // 注解实现延迟依赖注入处理过程
    public class AnnotationDependencyInjectionResolutionDemo {
    
        @Autowired // 依赖查找(处理)
        private User user;  // DependencyDescriptor ->
                            // 必须(required = true)
                            // (eager = true) 实时注入
                            // 通过类型(User.class)
                            // 字段名称("user")
                            // 是否是首要的(primary = true)
    
        @Autowired // 集合类型的依赖注入
        private Map<String, User> users; // user superUser
    
        @Inject
        private User injectUser;
    
        public static void main(String[] args) {
    
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
            AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
    
            // 期待输出superUser Bean
            System.out.println("demo.injectUser = " + demo.injectUser);
    
    
            // 显示的关闭spring应用上下文
            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

    19.Java通用注解注入原理

    CommonAnnotationBeanPostProcessor

    • 注入注解
      • javax.xml.ws.WebServiceRef
      • javax.ejb.EJB
      • javax.annotation.Resource
    • 生命周期注解
      • javax.annotation.PostConstruct
      • javax.annotation.PreDestroy

    其实CommonAnnotationBeanPostProcessor的处理和AutowiredAnnotationBeanPostProcessor的处理是差不多,这儿我们看下不同的地方,具体的如下:

    先来看下处理的类型:

    static {
    		try {
    			@SuppressWarnings("unchecked")
    			Class<? extends Annotation> clazz = (Class<? extends Annotation>)
    					ClassUtils.forName("javax.xml.ws.WebServiceRef", CommonAnnotationBeanPostProcessor.class.getClassLoader());
    			webServiceRefClass = clazz;
    		}
    		catch (ClassNotFoundException ex) {
    			webServiceRefClass = null;
    		}
    
    		try {
    			@SuppressWarnings("unchecked")
    			Class<? extends Annotation> clazz = (Class<? extends Annotation>)
    					ClassUtils.forName("javax.ejb.EJB", CommonAnnotationBeanPostProcessor.class.getClassLoader());
    			ejbRefClass = clazz;
    		}
    		catch (ClassNotFoundException ex) {
    			ejbRefClass = null;
    		}
    
      // @Resource 注解
    		resourceAnnotationTypes.add(Resource.class);
      // @WebServiceRef 注解
    		if (webServiceRefClass != null) {
    			resourceAnnotationTypes.add(webServiceRefClass);
    		}
      // @EJB 注解
    		if (ejbRefClass != null) {
    			resourceAnnotationTypes.add(ejbRefClass);
    		}
    	}
    
    • 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
    public CommonAnnotationBeanPostProcessor() {
    		setOrder(Ordered.LOWEST_PRECEDENCE - 3);
      // @PostConstruct注解
    		setInitAnnotationType(PostConstruct.class);
      // @PreDestroy 注解
    		setDestroyAnnotationType(PreDestroy.class);
      // @WebServiceContext 注解
    		ignoreResourceType("javax.xml.ws.WebServiceContext");
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    然后就是元数据的解析,具体的如下:

    @Override
    	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        // 调用父类的postProcessMergedBeanDefinition的方法,主要的是处理生命周期的元数据
    		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
    		InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
    		metadata.checkConfigMembers(beanDefinition);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    我们先来看看生命周期的元数据的处理,具体的如下:

    	@Override
    	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    		LifecycleMetadata metadata = findLifecycleMetadata(beanType);
    		metadata.checkConfigMembers(beanDefinition);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    	private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
    		if (this.lifecycleMetadataCache == null) {
    			// Happens after deserialization, during destruction...
    			return buildLifecycleMetadata(clazz);
    		}
    		// Quick check on the concurrent map first, with minimal locking.
    		LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
    		if (metadata == null) {
    			synchronized (this.lifecycleMetadataCache) {
    				metadata = this.lifecycleMetadataCache.get(clazz);
    				if (metadata == null) {
    					metadata = buildLifecycleMetadata(clazz);
    					this.lifecycleMetadataCache.put(clazz, metadata);
    				}
    				return metadata;
    			}
    		}
    		return metadata;
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    	private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
    		if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
    			return this.emptyLifecycleMetadata;
    		}
    
    		List<LifecycleElement> initMethods = new ArrayList<>();
    		List<LifecycleElement> destroyMethods = new ArrayList<>();
    		Class<?> targetClass = clazz;
    
    		do {
    			final List<LifecycleElement> currInitMethods = new ArrayList<>();
    			final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
    
    			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    				if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
    					LifecycleElement element = new LifecycleElement(method);
    					currInitMethods.add(element);
    					if (logger.isTraceEnabled()) {
    						logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
    					}
    				}
    				if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
    					currDestroyMethods.add(new LifecycleElement(method));
    					if (logger.isTraceEnabled()) {
    						logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
    					}
    				}
    			});
    
    			initMethods.addAll(0, currInitMethods);
    			destroyMethods.addAll(currDestroyMethods);
    			targetClass = targetClass.getSuperclass();
    		}
    		while (targetClass != null && targetClass != Object.class);
    
    		return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
    				new LifecycleMetadata(clazz, initMethods, destroyMethods));
    	}
    
    
    • 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

    上面的代码熟悉嘛?和前面的AutowiredAnnotationBeanPostProcessor几乎是一样的,这儿我不做过多的赘述了。然后处理完了生命周期的函数,我们再来看看需要注入的数据的处理。具体的如下:

    	private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
    		// Fall back to class name as cache key, for backwards compatibility with custom callers.
    		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    		// Quick check on the concurrent map first, with minimal locking.
    		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    			synchronized (this.injectionMetadataCache) {
    				metadata = this.injectionMetadataCache.get(cacheKey);
    				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    					if (metadata != null) {
    						metadata.clear(pvs);
    					}
    					metadata = buildResourceMetadata(clazz);
    					this.injectionMetadataCache.put(cacheKey, metadata);
    				}
    			}
    		}
    		return metadata;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    	private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
    		if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
    			return InjectionMetadata.EMPTY;
    		}
    
    		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    		Class<?> targetClass = clazz;
    
    		do {
    			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
    
    			ReflectionUtils.doWithLocalFields(targetClass, field -> {
    				if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
    					if (Modifier.isStatic(field.getModifiers())) {
    						throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
    					}
    					currElements.add(new WebServiceRefElement(field, field, null));
    				}
    				else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
    					if (Modifier.isStatic(field.getModifiers())) {
    						throw new IllegalStateException("@EJB annotation is not supported on static fields");
    					}
    					currElements.add(new EjbRefElement(field, field, null));
    				}
    				else if (field.isAnnotationPresent(Resource.class)) {
    					if (Modifier.isStatic(field.getModifiers())) {
    						throw new IllegalStateException("@Resource annotation is not supported on static fields");
    					}
    					if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
    						currElements.add(new ResourceElement(field, field, null));
    					}
    				}
    			});
    
    			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
    				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
    					return;
    				}
    				if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
    					if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
    						if (Modifier.isStatic(method.getModifiers())) {
    							throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
    						}
    						if (method.getParameterCount() != 1) {
    							throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
    						}
    						PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
    						currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
    					}
    					else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
    						if (Modifier.isStatic(method.getModifiers())) {
    							throw new IllegalStateException("@EJB annotation is not supported on static methods");
    						}
    						if (method.getParameterCount() != 1) {
    							throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
    						}
    						PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
    						currElements.add(new EjbRefElement(method, bridgedMethod, pd));
    					}
    					else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
    						if (Modifier.isStatic(method.getModifiers())) {
    							throw new IllegalStateException("@Resource annotation is not supported on static methods");
    						}
    						Class<?>[] paramTypes = method.getParameterTypes();
    						if (paramTypes.length != 1) {
    							throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
    						}
    						if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
    							PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
    							currElements.add(new ResourceElement(method, bridgedMethod, pd));
    						}
    					}
    				}
    			});
    
    			elements.addAll(0, currElements);
    			targetClass = targetClass.getSuperclass();
    		}
    		while (targetClass != null && targetClass != Object.class);
    
    		return InjectionMetadata.forElements(elements, clazz);
    	}
    
    • 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

    流程也是一样的,这儿也不做过多的赘述,我们再来看依赖查找和依赖的注入的流程,具体的如下:

    	@Override
    	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    		InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
    		try {
    			metadata.inject(bean, beanName, pvs);
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
    		}
    		return pvs;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    流程是一样的,这儿也不做过多的赘述。我们需要了解的是生命周期的函数的处理。前面的已经生成对应的LifecycleMetadata那么在什么地方调用呢?

    可以看到InitDestroyAnnotationBeanPostProcessor中的调用。具体的代码如下:

    初始化的方法

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    		try {
    			metadata.invokeInitMethods(bean, beanName);
    		}
    		catch (InvocationTargetException ex) {
    			throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
    		}
    		return bean;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    销毁的方法

    	@Override
    	public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
    		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    		try {
    			metadata.invokeDestroyMethods(bean, beanName);
    		}
    		catch (InvocationTargetException ex) {
    			String msg = "Destroy method on bean with name '" + beanName + "' threw an exception";
    			if (logger.isDebugEnabled()) {
    				logger.warn(msg, ex.getTargetException());
    			}
    			else {
    				logger.warn(msg + ": " + ex.getTargetException());
    			}
    		}
    		catch (Throwable ex) {
    			logger.warn("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    20.自定义依赖注入注解

    基于 AutowiredAnnotationBeanPostProcessor 实现

    自定义实现

    • 生命周期处理

      • InstantiationAwareBeanPostProcessor

      • MergedBeanDefinitionPostProcessor

    • 元数据

      • InjectedElement
      • InjectionMetadata

    第一种方式可以通过元注解的方式,具体的如下:

    package org.learn.spring.dependency.injection.annotation;
    
    import org.springframework.beans.factory.annotation.Autowired;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    // 自定义注解
    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Autowired
    public @interface MyAutowired {
    
        boolean required() default true;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.dependency.injection.annotation.MyAutowired;
    import org.learn.spring.ioc.overview.domain.User;
    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 javax.inject.Inject;
    import java.util.Collection;
    import java.util.Map;
    import java.util.Set;
    
    // 注解实现延迟依赖注入处理过程
    public class AnnotationDependencyInjectionResolutionDemo {
    
        @Autowired // 依赖查找(处理)
        private User user;  // DependencyDescriptor ->
                            // 必须(required = true)
                            // (eager = true) 实时注入
                            // 通过类型(User.class)
                            // 字段名称("user")
                            // 是否是首要的(primary = true)
    
        @Autowired // 集合类型的依赖注入
        private Map<String, User> users; // user superUser
    
        @MyAutowired
        private User injectUser;
    
        public static void main(String[] args) {
    
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
            AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
    
            // 期待输出superUser Bean
            System.out.println("demo.injectUser = " + demo.injectUser);
    
    
            // 显示的关闭spring应用上下文
            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

    通过自定义注解的方式,具体的代码如下:

    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.dependency.injection.annotation.InjectUser;
    import org.learn.spring.dependency.injection.annotation.MyAutowired;
    import org.learn.spring.ioc.overview.domain.User;
    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 javax.inject.Inject;
    import java.lang.annotation.Annotation;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.LinkedHashSet;
    import java.util.Map;
    import java.util.Set;
    
    import static org.springframework.context.annotation.AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME;
    
    // 注解实现延迟依赖注入处理过程
    public class AnnotationDependencyInjectionResolutionDemo {
    
        @Autowired // 依赖查找(处理)
        private User user;  // DependencyDescriptor ->
                            // 必须(required = true)
                            // (eager = true) 实时注入
                            // 通过类型(User.class)
                            // 字段名称("user")
                            // 是否是首要的(primary = true)
    
        @Autowired // 集合类型的依赖注入
        private Map<String, User> users; // user superUser
    
        @Inject
        private User injectUser;
    
        @InjectUser
        private User myInjectUser;
    
        // 标记成static字段的话,会提前初始化
        @Bean(value = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)
        public static AutowiredAnnotationBeanPostProcessor beanPostProcessor(){
            AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
            // @Autowired + @Inject + 新的注解@InjectUser处理
            Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(Arrays.asList(Autowired.class, Inject.class, InjectUser.class));
            autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
            return autowiredAnnotationBeanPostProcessor;
        }
    
        public static void main(String[] args) {
    
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
            AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
    
            // 期待输出superUser Bean
            System.out.println("demo.user = " + demo.user);
            System.out.println("demo.injectUser = " + demo.injectUser);
            System.out.println("demo.myInjectUser = " + demo.myInjectUser);
    
    
            // 显示的关闭spring应用上下文
            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
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    但是上面的代码如果Inject.class如果不存在时候就会报错,不安全,那么我们可以改成如下的:

    package org.learn.spring.dependency.injection;
    
    import org.learn.spring.dependency.injection.annotation.InjectUser;
    import org.learn.spring.dependency.injection.annotation.MyAutowired;
    import org.learn.spring.ioc.overview.domain.User;
    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.core.Ordered;
    import org.springframework.core.annotation.Order;
    
    import javax.inject.Inject;
    import java.lang.annotation.Annotation;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.LinkedHashSet;
    import java.util.Map;
    import java.util.Set;
    
    import static org.springframework.context.annotation.AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME;
    
    // 注解实现延迟依赖注入处理过程
    public class AnnotationDependencyInjectionResolutionDemo {
    
        @Autowired // 依赖查找(处理)
        private User user;  // DependencyDescriptor ->
        // 必须(required = true)
        // (eager = true) 实时注入
        // 通过类型(User.class)
        // 字段名称("user")
        // 是否是首要的(primary = true)
    
        @Autowired // 集合类型的依赖注入
        private Map<String, User> users; // user superUser
    
        @Inject
        private User injectUser;
    
        @InjectUser
        private User myInjectUser;
    
        // 标记成static字段的话,会提前初始化
        /*@Bean(value = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)
        public static AutowiredAnnotationBeanPostProcessor beanPostProcessor(){
            AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
            // @Autowired + @Inject + 新的注解@InjectUser处理
            Set> autowiredAnnotationTypes = new LinkedHashSet<>(Arrays.asList(Autowired.class, Inject.class, InjectUser.class));
            autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
            return autowiredAnnotationBeanPostProcessor;
        }*/
    
      // 新老注解同时存在
        @Bean
        @Order(Ordered.LOWEST_PRECEDENCE - 3)
        public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
            AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
            autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectUser.class);
            return autowiredAnnotationBeanPostProcessor;
        }
    
        public static void main(String[] args) {
    
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
    
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
    
            String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
            // 加载XML资源,解析并生成BeanDefinition
            beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
            AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
    
            // 期待输出superUser Bean
            System.out.println("demo.user = " + demo.user);
            System.out.println("demo.injectUser = " + demo.injectUser);
            System.out.println("demo.myInjectUser = " + demo.myInjectUser);
    
    
            // 显示的关闭spring应用上下文
            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
    • 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

    21.面试题

    有多少种依赖注入的方式?

    • 构造器注入
    • Setter 注入
    • 字段注入
    • 方法注入
    • 接口回调注入

    你偏好构造器注入还是 Setter 注入?

    两种依赖注入的方式均可使用, 如果是必须依赖的话, 那么推荐使用构造器注入, Setter 注入用于可选依赖。

  • 相关阅读:
    8.Docker MySQL 主从复制
    禾匠商城系统 企业转账到零钱 修改成 商家转账到零钱
    使用Spring进行文件的上传和下载
    【linux内核调试】- centos7安装systemtap
    Vue入门简介(带你打开Vue的大门)
    牛客多校4 N Particle Arts
    初见JAVA —— 最基础的变量,选择,循环语句,数组,方法,输入与输出等
    【软考 系统架构设计师】项目管理⑤ 软件配置管理
    Linux补充知识:
    CompletionService 和 CompletableFuture
  • 原文地址:https://blog.csdn.net/qq_36434742/article/details/128021441