spring IOC

IOC配置方式

xml 配置

1. 构造器注入(Constructor Injection)

构造器注入通过构造函数将依赖关系传递给目标对象。这种方式确保了依赖项在对象创建时即被提供,因此特别适合于那些依赖项是必须的场景。构造器注入也有助于确保对象的不可变性。

示例:
@Component
public class MyService {
​
    private final MyRepository repository;
​
    @Autowired
    public MyService(MyRepository repository) {
        this.repository = repository;
    }
​
    // Other methods
}

在上面的例子中,@Autowired 注解指示 Spring 通过构造器注入 MyRepository 对象。

2. Setter 注入(Setter Injection)

Setter 注入通过 setter 方法将依赖关系注入目标对象。这种方式适用于可选的依赖项,或者依赖项可以在对象创建后进行修改的场景。

示例:
@Component
public class MyService {
​
    private MyRepository repository;
​
    @Autowired
    public void setRepository(MyRepository repository) {
        this.repository = repository;
    }
​
    // Other methods
}

在这个例子中,@Autowired 注解指示 Spring 通过 setter 方法注入 MyRepository 对象。

3. 字段注入(Field Injection)

字段注入直接将依赖关系注入到目标对象的字段中。这种方式非常简洁,但通常不推荐,因为它使得对象的依赖关系不够明确,并且不利于单元测试。

示例:
@Component
public class MyService {
​
    @Autowired
    private MyRepository repository;
​
    // Other methods
}

在这个例子中,@Autowired 注解指示 Spring 直接将 MyRepository 对象注入到 repository 字段中。

4. 方法注入(Method Injection)

方法注入通过将依赖项传递给目标对象中的某个方法来实现。这种方式比较少见,但在某些场景中(例如,依赖项的创建在特定的方法调用时才需要)可能会有用。

示例:
java复制代码
public class MyService {
​
    private MyRepository repository;
​
    @Autowired
    public void injectRepository(MyRepository repository) {
        this.repository = repository;
    }
​
    // Other methods
}

在这个例子中,@Autowired 注解指示 Spring 调用 injectRepository 方法将 MyRepository 对象注入到 MyService 中。

5. 构造器注入(Constructor Injection)的变体(基于 @Value 注解)

除了使用 @Autowired 注解来进行构造器注入外,还可以使用 @Value 注解来注入简单的值,例如配置文件中的值。

示例:
@Component
public class MyService {
​
    private final String appName;
​
    @Autowired
    public MyService(@Value("${app.name}") String appName) {
        this.appName = appName;
    }
​
    // Other methods
}

在这个例子中,@Value("${app.name}") 用于将配置文件中的 app.name 属性值注入到 appName 字段中。

6. 注入集合(Collection Injection)

Spring 还支持将集合类型的依赖项注入到目标对象中,这对于需要动态管理一组对象的场景非常有用。

示例:
@Component
public class MyService {
​
    private final List<MyRepository> repositories;
​
    @Autowired
    public MyService(List<MyRepository> repositories) {
        this.repositories = repositories;
    }
​
    // Other methods
}

在这个例子中,repositories 是一个 List,Spring 会自动注入所有 MyRepository 类型的 Bean 到这个列表中。

IOC常用注解

@Autowired

@Autowired 注解可以应用于构造方法、setter 方法、字段和方法参数。以下是每种用法的示例:

1. 构造方法注入

构造方法注入是通过构造方法将依赖项注入到 Bean 中。这是推荐的注入方式,特别是当依赖项是必需的时,因为它可以确保依赖项在 Bean 创建时已经被注入。

@Component
public class MyService {
​
    private final MyRepository repository;
​
    @Autowired
    public MyService(MyRepository repository) {
        this.repository = repository;
    }
​
    // Other methods
}

在这个例子中,@Autowired 注解标记了构造方法,Spring 会自动注入 MyRepository 的实例。

2. Setter 方法注入

Setter 方法注入是通过 setter 方法将依赖项注入到 Bean 中。这种方式适用于可选的依赖项,或者依赖项可能在 Bean 创建之后发生变化的场景。

@Component
public class MyService {
​
    private MyRepository repository;
​
    @Autowired
    public void setRepository(MyRepository repository) {
        this.repository = repository;
    }
​
    // Other methods
}

在这个例子中,@Autowired 注解标记了 setter 方法,Spring 会自动注入 MyRepository 的实例。

3. 字段注入

字段注入是直接将依赖项注入到 Bean 的字段中。这种方式简洁,但一般不推荐,因为它使得对象的依赖关系不够明确,并且不利于单元测试。

@Component
public class MyService {
​
    @Autowired
    private MyRepository repository;
​
    // Other methods
}

在这个例子中,@Autowired 注解标记了字段,Spring 会自动注入 MyRepository 的实例。

4. 方法参数注入

方法参数注入是将依赖项作为方法参数传递给 Bean 的方法。虽然这种方式较少用,但在某些场景下可能会有用。

@Component
public class MyService {
​
    private MyRepository repository;
​
    @Autowired
    public void configure(MyRepository repository) {
        this.repository = repository;
    }
​
    // Other methods
}

在这个例子中,@Autowired 注解标记了方法参数,Spring 会自动注入 MyRepository 的实例。

处理流程

扫描和解析注解

  • Spring 容器在启动时,会扫描指定的包路径下的类,查找带有 @Autowired 注解的字段、构造函数或方法。

  • Spring 使用反射技术来获取这些注解的元数据(如注解的类型、位置、修饰的元素等)。

依赖注入逻辑

  • 对于标记了 @Autowired 注解的字段、构造函数或方法,Spring 会尝试根据类型在容器中查找合适的 bean 实例。

  • 如果找到唯一的匹配 bean,Spring 会将其注入到标记了 @Autowired 的位置。

  • 如果有多个匹配的 bean,Spring 会尝试根据 bean 名称或其他限定符(如 @Qualifier 注解)来进一步筛选。如果仍然不能确定唯一的 bean,Spring 会抛出异常。

处理构造函数注入

  • 如果 @Autowired 应用于构造函数,并且类只有一个构造函数,则 Spring 会自动使用该构造函数进行注入,即使没有明确标注 @Autowired

  • Spring 会自动解析构造函数的参数类型,并在容器中查找匹配的 bean 进行注入。

处理方法和字段注入

  • 对于方法,Spring 会调用该方法,并传入匹配的 bean 实例作为参数。

  • 对于字段,Spring 会通过反射直接设置字段的值。

  • 在 Spring Boot 项目中,@Resource 注解用于依赖注入。它是 Java 自带的标准注解,属于 javax.annotation 包。@Resource 既可以注入 Bean,也可以注入 Java 原生资源(如文件、数据库连接等)。它的工作方式类似于 Spring 的 @Autowired 注解,但有一些不同的特性和用途。

@Resource

  1. 按名称注入

    • 如果没有指定 name 属性,@Resource 会默认按照变量名去寻找匹配的 Bean。如果找到一个匹配的 Bean,就会进行注入。

    • 如果指定了 name 属性,则按指定的名称查找 Bean 并注入。

    @Resource(name = "myService")
    private MyService myService;
  2. 按类型注入

    • 如果没有指定 name 属性且找不到按名称匹配的 Bean,@Resource 会尝试按照类型进行注入。

    @Resource
    private MyService myService;

@Autowired 的区别:

注入方式

  • @Autowired 是 Spring 提供的注解,默认是按类型注入,也可以搭配 @Qualifier 按名称注入。

  • @Resource 是 Java 标准注解,默认是按名称注入,如果没有指定名称则按类型注入。

依赖注入解析顺序

  • @Resource 首先按名称查找 Bean,如果找不到再按类型查找。

  • @Autowired 直接按类型查找,除非使用 @Qualifier 指定名称。

注解来源

@Autowired 来自于 Spring 框架。

@Resource 来自于 Java EE(现在属于 Jakarta EE)。

@Inject

按照类型进行自动装配的

多个Bean对象进行依赖处理

1. @Qualifier 注解

@Qualifier 注解用于明确指定要注入的 Bean。当存在多个相同类型的 Bean 时,通过 @Qualifier 注解可以告诉 Spring 选择哪个具体的 Bean 进行注入。

使用方法
  • 在构造方法中

    @Component
    public class MyService {
    ​
        private final MyRepository repository;
    ​
        @Autowired
        public MyService(@Qualifier("mySpecificRepository") MyRepository repository) {
            this.repository = repository;
        }
    ​
        // Other methods
    }

    在这个例子中,@Qualifier("mySpecificRepository") 指定了注入的 Bean 名称为 mySpecificRepository

  • 在 setter 方法中

    @Component
    public class MyService {
    ​
        private MyRepository repository;
    ​
        @Autowired
        public void setRepository(@Qualifier("mySpecificRepository") MyRepository repository) {
            this.repository = repository;
        }
    ​
        // Other methods
    }

    同样,@Qualifier("mySpecificRepository") 用于指定要注入的 Bean。

  • 在字段中

    @Component
    public class MyService {
    ​
        @Autowired
        @Qualifier("mySpecificRepository")
        private MyRepository repository;
    ​
        // Other methods
    }

    @Qualifier("mySpecificRepository") 直接用于字段注入,明确指定注入的 Bean。

2. @Primary 注解

@Primary 注解用于标记当存在多个相同类型的 Bean 时,Spring 默认注入哪个 Bean。如果没有使用 @Qualifier 注解进行显式指定,Spring 会优先注入被标记为 @Primary 的 Bean。

示例:
@Component
@Primary
public class MyPrimaryRepository implements MyRepository {
    // Implementation details
}
​
@Component
public class MySecondaryRepository implements MyRepository {
    // Implementation details
}

在这个例子中,MyPrimaryRepository 被标记为 @Primary,因此如果在没有 @Qualifier 注解的情况下进行注入,Spring 会选择 MyPrimaryRepository

3. 自定义注解

在某些复杂的场景中,你可能需要自定义注解来标识不同的 Bean。例如,你可以创建自己的注解,并与 @Qualifier 注解结合使用。

自定义注解示例:
  • 定义注解

    @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Qualifier
    public @interface MySpecialQualifier {
    }

  • 使用注解

    @Component
    public class MyService {
    ​
        private final MyRepository repository;
    ​
        @Autowired
        public MyService(@MySpecialQualifier MyRepository repository) {
            this.repository = repository;
        }
    ​
        // Other methods
    }

    在这个例子中,@MySpecialQualifier 是一个自定义的注解,用于指定注入的 Bean。

4. 其他高级配置

在复杂应用中,你也可以使用 Java 配置类和 XML 配置文件来定义 Bean 的注入规则。例如,你可以在配置类中使用 @Bean 注解和方法参数来明确指定 Bean 的创建和依赖关系。

Java 配置类示例:
@Configuration
public class AppConfig {
​
    @Bean
    @Primary
    public MyRepository myPrimaryRepository() {
        return new MyPrimaryRepository();
    }
​
    @Bean
    public MyRepository mySecondaryRepository() {
        return new MySecondaryRepository();
    }
}

在这个配置类中,通过 @Primary 注解和 @Bean 方法明确指定了默认的 Bean。

控制反转(IoC)

  • 传统情况下,应用程序的各个组件通常会自己管理它们的依赖对象,称为"正向控制"。而在IoC中,这种控制被反转了。组件的依赖不再由它们自己创建或获取,而是由IoC容器负责注入,这样做可以解耦组件,使得代码更容易测试和维护。

依赖注入(DI,Dependency Injection)

  • IoC最常见的一种实现方式就是依赖注入。依赖注入是指在运行时,IoC容器将所需的依赖对象注入到组件中,而不是让组件自己去查找或创建这些对象。

  • DI可以通过构造器注入、Setter方法注入或接口注入等多种方式实现。

    主要的实现步骤和原理

    扫描和解析注解

    • Spring 容器在启动时,会扫描指定的包路径下的类,查找带有 @Autowired 注解的字段、构造函数或方法。

    • Spring 使用反射技术来获取这些注解的元数据(如注解的类型、位置、修饰的元素等)。

    依赖注入逻辑

    • 对于标记了 @Autowired 注解的字段、构造函数或方法,Spring 会尝试根据类型在容器中查找合适的 bean 实例。

    • 如果找到唯一的匹配 bean,Spring 会将其注入到标记了 @Autowired 的位置。

    • 如果有多个匹配的 bean,Spring 会尝试根据 bean 名称或其他限定符(如 @Qualifier 注解)来进一步筛选。如果仍然不能确定唯一的 bean,Spring 会抛出异常。

    处理构造函数注入

    • 如果 @Autowired 应用于构造函数,并且类只有一个构造函数,则 Spring 会自动使用该构造函数进行注入,即使没有明确标注 @Autowired

    • Spring 会自动解析构造函数的参数类型,并在容器中查找匹配的 bean 进行注入。

    处理方法和字段注入

    • 对于方法,Spring 会调用该方法,并传入匹配的 bean 实例作为参数。

    • 对于字段,Spring 会通过反射直接设置字段的值。

    required 属性

    @Autowired 注解的 required 属性默认为 true,这意味着如果没有找到匹配的 bean,Spring 会抛出 NoSuchBeanDefinitionException 异常。

    如果 required 设置为 false,则在没有匹配的 bean 时,Spring 不会注入该字段或参数,保持其默认值(例如 null)。

    参考文章

    Spring基础 - Spring核心之控制反转(IOC) | Java 全栈知识体系

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值