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

news2024/11/16 16:01:42

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) 限制和不足

官方说明

  • Limitations and Disadvantages of Autowiring 小节
  • 在这里插入图片描述

6.Setter 方法注入

实现方法

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

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

XML 资源配置元信息

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="classpath:/META-INF/dependency-lookup-context.xml"/>

    <bean class="org.learn.spring.dependency.injection.UserHolder">
        <property name="user" ref="superUser"/>
    </bean>

</beans>
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);
    }
}

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;
    }
}

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();
    }

}

byName

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="classpath:/META-INF/dependency-lookup-context.xml"/>

    <bean class="org.learn.spring.dependency.injection.UserHolder" autowire="byName"/>

</beans>
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);
    }

}

byType

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="classpath:/META-INF/dependency-lookup-context.xml"/>

    <bean class="org.learn.spring.dependency.injection.UserHolder" autowire="byType"/>

</beans>
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);
    }

}

7.构造器注入

实现方法

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

下面来展示示例代码

XML 资源配置元信息

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="classpath:/META-INF/dependency-lookup-context.xml"/>

    <bean class="org.learn.spring.dependency.injection.UserHolder">
        <constructor-arg name="user" ref="superUser"/>
    </bean>

</beans>
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);
    }
}

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);
    }
}

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();
    }

}

constructor

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="classpath:/META-INF/dependency-lookup-context.xml"/>

    <bean class="org.learn.spring.dependency.injection.UserHolder" autowire="constructor"/>

</beans>
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);
    }

}

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);
    }
}

@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);
    }
}

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);
    }
}

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;
    }
}

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 等

具体的代码如下:

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean 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>
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 +
                '}';
    }
}


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);
        }
    }
}

13.集合类型注入

集合类型

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

具体的代码如下:

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean 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>BEIJING</value>
                <value>HANGZHOU</value>
                <value>SHANGHAI</value>
            </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>
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 +
                '}';
    }
}

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);
        }
    }
}

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 {
}

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();

    }
}

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();

    }
}

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;
  }
}

我们先来看第一个参数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;
  
}

上面只是简单的分析了一下,比较模糊,下面我们通过一个简单的例子和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();

    }
}

我们在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;
  }
}

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();
		}
	}

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

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

然后会直接调用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);
  }
}

这儿我们需要了解是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;
}

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

@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);
  }
}

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

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();

    }
}

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

@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);
  }
}

这儿直接调用的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;
		}
	}

由于这儿返回不是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);
			}
		}

这个时候我们需要通过对应的调用栈继续往上查找,先看到的是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);
}

我们需要看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;
	}
	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);
	}

通过上面的分析,元信息解析是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.
		}
	}

那么是怎么去针对出现多个对应的注解查找呢?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;
	}

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

<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-core</artifactId>
        <groupId>org.learn.spring</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>dependency-injection</artifactId>

    <dependencies>
        <dependency>
            <groupId>${groupId}</groupId>
            <artifactId>ioc-container-overview</artifactId>
            <version>${version}</version>
            <scope>compile</scope>
        </dependency>

        <!-- JSR 303 -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
    </dependencies>
</project>

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();

    }
}

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);
		}
	}
public CommonAnnotationBeanPostProcessor() {
		setOrder(Ordered.LOWEST_PRECEDENCE - 3);
  // @PostConstruct注解
		setInitAnnotationType(PostConstruct.class);
  // @PreDestroy 注解
		setDestroyAnnotationType(PreDestroy.class);
  // @WebServiceContext 注解
		ignoreResourceType("javax.xml.ws.WebServiceContext");
	}

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

@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);
	}

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

	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		LifecycleMetadata metadata = findLifecycleMetadata(beanType);
		metadata.checkConfigMembers(beanDefinition);
	}
	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;
	}

	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));
	}

上面的代码熟悉嘛?和前面的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;
	}
	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);
	}

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

	@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;
	}

流程是一样的,这儿也不做过多的赘述。我们需要了解的是生命周期的函数的处理。前面的已经生成对应的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;
	}

销毁的方法

	@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);
		}
	}

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;
}

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();

    }
}

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

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();

    }
}

但是上面的代码如果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<Class<? extends Annotation>> 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();

    }
}

21.面试题

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32266.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为机试 - 最大括号深度

目录 题目描述 输入描述 输出描述 用例 题目解析 算法源码 题目描述 现有一字符串仅由 ‘(‘&#xff0c;’)’&#xff0c;{‘&#xff0c;’}’&#xff0c;[‘&#xff0c;’]’六种括号组成。 若字符串满足以下条件之一&#xff0c;则为无效字符串&#xff1a; ①…

【MySQL】拿来即用 —— MySQL中的数据类型

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ MySQL数据类型⚪熟悉SQL一、MySQL数据类型总结…

设备树和设备树语法

设备树 驱动代码只负责处理驱动的逻辑&#xff0c;而关于设备的具体信息存放到设备树文件中。许多硬件设备信息可以直 接通过它传递给 Linux&#xff0c;而不需要在内核中堆积大量的冗余代码。 设备树&#xff0c;将这个词分开就是“设备”和“树”&#xff0c;描述设备树的文…

【计算机毕业设计】22.毕业设计选题系统ssm源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 引言 近年来&#xff0c;电子商务发展的愈趋成熟使得人们的消费方式以及消费观念发生巨大改变&#xff0c;网上竞拍的拍卖模式随之发展起来。大学拍卖网旨在为湘大学生提供一个线上拍卖的交易平台。平台展示的商品大…

【American English】美式发音,英语发音,美国音音标列表及发音

首先声明&#xff0c;网上各种英式发音和美式发音的教程&#xff0c;而我的目的是寻找美式发音。但是自己现在也是在不断地找寻中&#xff0c;所以资料找错了请莫怪。另外&#xff0c;资料顺序采用部分倒叙&#xff0c;不喜请勿吐槽。 文章目录发音示意图49. [](https://www.bi…

百度地图有感

以前总认为坚持会让我们变强大&#xff0c;但是长大后发现&#xff0c;让我们强大的&#xff0c;是放下。 生活也许就是这样&#xff0c;多一分经验便少一分幻想&#xff0c;以实际的愉快平衡现实的痛苦。 百度地图开放平台 百度地图入门指南 百度地图开发指南 百度地图API文…

性早熟和微生物群:性激素-肠道菌群轴的作用

谷禾健康 肠道菌群 & 性激素 青春期是生命的一个关键阶段&#xff0c;与性成熟相关的生理变化有关&#xff0c;是一个受多种内分泌和遗传控制调控的复杂过程。 青春期发育可以在适当的时候&#xff0c;早熟或延迟。 未经治疗的性早熟的孩子通常不会达到成年身高的全部潜力。…

Activity的最佳实践

文章目录Activity的最佳实践知晓当前是在哪一个Activiy随时随地退出程序启动Activity的最佳写法Activity的最佳实践 知晓当前是在哪一个Activiy 创建一个BaseActivity类,继承AppCompatActivity类.重写onCreate方法 open class BaseActivity : AppCompatActivity() {override…

xilinx PL测 DP 点屏 /接收(二)--RX

环境&#xff1a; a)硬件&#xff1a;官方ZCU106开发板 , tb-fmch-vfmc-dp子卡。 b)软件&#xff1a;vivado2021.1&#xff0c;vitis2021.1&#xff0c;裸机程序。 1、官方例程&#xff1a; 2、DP RX IP &#xff1a; 3、DP RX寄存器&#xff1a; 4、时钟&#xff1a; 5、像素&…

CentOS 6.6系统怎么安装?CentOS Linux系统安装配置图解教程

服务器相关设置如下&#xff1a; 操作系统&#xff1a;CentOS 6.6 64位 IP地址&#xff1a;192.168.21.129 网关&#xff1a;192.168.21.2 DNS&#xff1a;8.8.8.8 8.8.4.4 备注&#xff1a; CentOS 6.6系统镜像有32位和64位两个版本&#xff0c;并且还有专门针对服务器优化过的…

【端到端存储解决方案】Weka,让企业【文件存储】速度飞起来!

一、HK-Weka概述 虹科WekaIO&#xff08;简称HK-Weka&#xff09;是一个可共享、可扩展的文件存储系统解决方案&#xff0c;其并行文件系统WekaFS支持NVMeoF的flash-native并行文件系统、比传统的NAS存储及本地存储更快。 HK-Weka后端主机被配置为集群&#xff0c;它与安装在应…

在Mysql中新建序列Sequence

在Oracle数据库中想要一个连续的自增数据类型的值&#xff0c;可以通过创建一个sequence来实现。而在Mysql数据库中并没有sequence&#xff0c;如想要在Mysql中像Oracle那样使用序列&#xff0c;该如何操作呢&#xff1f;&#xff08;可以使用mysql中的自增主键&#xff09; 1、…

哪个牌子的led灯质量好?2022LED护眼台灯最好的品牌有哪些

谈及led灯的品牌&#xff0c;就不得不提一些比较专业的厂商了&#xff0c;特别是在护眼照明领域&#xff0c;明基、南卡、飞利浦、松下等品牌都有不俗的实力&#xff0c;出产的led护眼台灯在业内都有广泛的知名度&#xff0c;在消费者领域也是好评连连。那么它们到底好在哪儿呢…

蓝牙协议栈分层

一、分层 BLE协议栈主要用来对你的应用数据进行层层封包&#xff0c;以生成一个满足BLE协议的空中数据包&#xff0c;也就是说&#xff0c;把应用数据包裹在一系列的帧头&#xff08;header&#xff09;和帧尾&#xff08;tail&#xff09;中。 BLE协议栈主要由如下几部分组成…

达梦日志分析工具DMLOG使用

达梦日志分析工具DMLOG1.使用工具的目的2.适用范围3.工具描述4.开启跟踪日志记录执行SQL5.使用条件及限制6.使用说明6.1使用前准备6.2使用方法和步骤7.结果解读1.使用工具的目的 分析SQL是DBA或者数据库服务人员很重要的工作。达梦数据库通过开启SVR_LOG捕捉数据库中运行的所有…

SpringBoot+Vue项目实现高校学生健康打卡系统

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…

双通道PID控制器用于热离子发电器中真空度和温度的同时控制

摘要&#xff1a;本文针对真空型热离子能量转换器&#xff08;发电装置&#xff09;中真空压力和温度的关联性复杂控制&#xff0c;提出一个简便的控制方式和控制系统的解决方案&#xff0c;控制系统仅采用一个双通道高精度PID调节器。方案的核心技术思路是将一个可调参量转换为…

接口类型太多了,很多网工总是分不清

交换机光模块的最强科普 以太网交换机常用的光模块有四个&#xff0c;分别是SFP&#xff08;Small Form-factor Pluggabletransceiver&#xff09; 小封装可插拔收发器&#xff0c;GBIC&#xff08;GigaBit Interface Converter&#xff09;千兆以太网接口转换器&#xff0c;X…

往USBKey里面导入双证书专题:概念介绍、执行逻辑

相关概念 国密证书 国密的双证书体系&#xff0c;将证书按照使用目的的不同划分为加密证书和签名证书两种&#xff0c;也就是两对公私钥&#xff0c;二者本质一致&#xff0c;均为SM2密钥对&#xff0c;区别仅体现在用法国密CA体系中&#xff0c;加密密钥对由CA产生&#xff…

力扣刷题记录141.1-----34. 在排序数组中查找元素的第一个和最后一个位置

目录一、题目二、代码三、运行结果一、题目 二、代码 class Solution { public:vector<int> searchRange(vector<int>& nums, int target) {int i,j;int left,right,middle;vector<int> return_vector(2,-1);if(nums.size()<3){for(i0;i<nums.si…