开发者

基于@Autowired依赖注入的原理分析

目录
  • 1、介绍
  • 2、实现原理
    • 1、扫描及注册 Bean
    • 2、解析依赖
    • 3、类型匹配
  • 3、使用场景
    • 3.1、背景
    • 3.2、处理方式
      • 1、@Qualifier
      • 2、@Primary注解
    • 3.3、替代方式
      • 1. @Inject
      • 2. 构造函数注入
      • 3. @Resource
  • 4、总结

    @Autowired 是 Spring 框架中的一个注解,用于自动注入依赖。

    在 Spring 中miRbpBQx,依赖注入(Dependency Injection, DI)是一种设计模式,允许在运行时将对象的依赖关系(即所需的其他对象)自动提供给它,而不是在代码中手动创建依赖对象。

    1、介绍

    以下为注解的结构图

    基于@Autowired依赖注入的原理分析

    该注解支持标注在字段、构造函数、方法以及参数上。

    注意:

    其中的关键属性 required 默认值为 true,表示如果没有合适的 Bean 可以注入,则会抛出异常。required 如果为false的时候,表示可以暂时不实例化。

    @Target({ElementType.CONSTRUCTOR, Elemehttp://www.devze.comntType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Autowired {
        boolean required() default true;
    }

    2、实现原理

    1、扫描及注册 Bean

    Spring 在启动时会扫描配置的包,找到被@Compoent、@Service、@Repository和@Controller等注解标记的类,并将它们注册为 Spring 容器中的 Beans。

    2、解析依赖

    当 Spring 创建一个 Bean 时,它会检查该 Bean 的构造函数、方法或字段中是否有@Autowired注解。

    这个注解表明该字段、构造函数或方法是需要进行依赖注入的。

    3、类型匹配

    Spring 会根据变量的类型去容器中查找匹配的 Bean,默认情况下,Spring 使用的是按类型自动装配。

    • 如果找到唯一的匹配项,就会将其注入。
    • 如果有多个匹配项,Spring 会抛出异常;可以通过设置required=false或者使用 @Qualifier或者@Primary来解决歧义问题。
    • 如果没有匹配项,通常会返回 null(前提是字段是可空的)。

    3、使用场景

    3.1、背景

    当 Spring 容器检测到有多个同类型的 Bean 可供注入时,默认的行为是抛出 NoUniqueBeanDefinitionException 异常。

    3.2、处理方式

    1、@Qualifier

    如果有多个相同类型的 Bean 时,可以使用 @Qualifier 注解来明确指定要注入的 Bean。

    代码示例:

    @Autowired
    @Qualifier("specificBeanName")
    private MyService myService;

    2、@Primary注解

    基于@Autowired依赖注入的原理分析

    1、目的

    主要目的是在 Spring 容器中有多个相同类型的 Bean 存在时,提供一种机制来指定哪个 Bean 应该被优先考虑作为默认注入的目标。

    2、原理

    如果其中一个 Bean 被标记为 @Primary,那么 Spring 将会选择它作为首选项并完成注入过程。

    此逻辑发生在 Spring 的自动装配阶段,在这一阶段,容器会评估所有可用的候选 Bean,并根据各种规则(如 @Primary@Qualifier 等)做出最终决策

    3、示例

    @Configuration
    public class AppConfig {
    
        @Bean
        @Primary
        public MyService primaryMyService() {
            return new MyServiceImpl1();
        }
    
        @Bean
        public MyService secondaryMyService() {
     编程       return new MyServiceImpl2();
        }
    }

    在这个配置文件中,我们有两个实现了 MyService接口的服务类——MyServiceImpl1 和 MyServiceImpl2。由于我们在第一个服务实现上加了 @Primary 注解,因此无论何时需要注入 MyService类型的对象,都会优先选取 MyServiceImpl1 实例。

    3.3、替代方式

    1. @Inject

    @Inject 是 Java EE 提供的标准注解,也可以在 Spring 中使用。

    它的功能类似于@Autowired,但语义更加清晰,因为它仅关注依赖注入本身而不涉及 Spring 特定的功能。

    public class ExampleService {
        private final AnotherService anotherService;
    
        @Inject
        public ExampleService(AnotherService anotherService) {
            this.anotherService = anotherService;
        }
    }

    2. 构造函数注入

    这种方式编程被认为是最佳实践之一,尤其适用于强制性依赖项。相比于字段注入或 setter 方法注入,构造函数注入能更好地满足不可变性和测试需求。

    示例:

    public class UserService {
        private final UserRepository userRepository;
    
        public UserService(UserRepository userRepository) { // 构造函数注入
            this.userRepository = userRepository;
        }
    }

    3. @Resource

    @Resource 是 JNDI 规范的一部分,通常基于名称匹配来查找目标 Bean。

    如果没有找到与名字完全一致的 Bean,则会退回到按类型匹配的方式。相比 @Autowired 更加灵活,因为可以直接指定要注入的具体资源名。

    示例:

    public class MovieRecommender {
        @Resource(name="mainDataSource") // 明确指定了数据源的名字
        DataSource dataSource;
        
        public void recommend() {}
    }

    4、总结

    通俗讲解

    把@Autowired看成是一种“智能化的手”。当你需要一个助手(依赖对象)来完成某个任务时,你不需要去亲自找寻和雇佣这个助手,Spring 就像一个高效的秘书,知道你需要什么助手,会自动给你安排好。

    你只需要告诉 Spring 你需要的助手的类型,它就会负责寻找并提供给你,而不需要你关心具体的细节。

    这样做的好处是可以降低代码的耦合度,让程序的各个部分更容易进行单元测试和维护python。只要我们在代码中声明需要的依赖,Spring 就会负责去处理这些依赖,让开发者能更专注于业务逻辑的实现。

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜