您现在的位置是:首页 > 编程 > 

【Spring】DI依赖注入的三种方式

2025-07-26 20:29:56
【Spring】DI依赖注入的三种方式 引入上一篇文章介绍了@Bean注解的使用和扫描路径的配置,本文主要介绍如何将交给Spring管理的Bean对象怎样注入,也就是使用Bean对象一:DI详解依赖注入是一个过程,指在IoC容器创建Bean的时候,提供对象这个资源,之前我们学习了@Autowired这个注解,完成依赖注入,即把对象取出来,放到某个类的属性中去。Spring提供了三种依赖注入的方式1

【Spring】DI依赖注入的三种方式

引入

上一篇文章介绍了@Bean注解的使用和扫描路径的配置,本文主要介绍如何将交给Spring管理的Bean对象怎样注入,也就是使用Bean对象

一:DI详解

依赖注入是一个过程,指在IoC容器创建Bean的时候,提供对象这个资源,之前我们学习了@Autowired这个注解,完成依赖注入,即把对象取出来,放到某个类的属性中去。

Spring提供了三种依赖注入的方式

1:属性注入

属性注⼊是使⽤ @Autowired 实现的,将Service类注⼊到Controller类中.

(1)Service类的实现代码如下

代码语言:javascript代码运行次数:0运行复制
import org.springframework.stereotype.Service;
@Service
public class UserService {
    public void sayHi() {
        println("Hi,UserService");
    }
}

(2)Controller 类的实现代码如下:

代码语言:javascript代码运行次数:0运行复制
@Controller
public class UserController {
    // 注⼊⽅法1: 属性注⼊
    @Autowired
    private UserService userService;

    public void sayHi() {
        println("hi,UserController...");
        userService.sayHi();
    }
}

()获取Controller中的sayHi⽅法:

代码语言:javascript代码运行次数:0运行复制
@SpringBootApplication
public class SpringIocDemoApplication {
    public static void main(String[] args) {
        // 获取Spring上下⽂对象
        ApplicationContext context = SpringApplication.run(, args);
        // 从Spring上下⽂中获取对象
        UserController userController = (UserController) context.getBean("userController");
        // 使⽤对象
        userController.sayHi();
    }
}

运行结果

2:构造方法注入

注意:

如果类只有⼀个构造⽅法,那么@Autowired 注解可以省略;

如果类中有多个构造⽅法, 那么需要添加上@Autowired 来明确指定到底使⽤哪个构造⽅法。

代码语言:javascript代码运行次数:0运行复制
@Controller
public class UserController2 {
    // 注⼊⽅法2: 构造⽅法
    private UserService userService;

    @Autowired
    public UserController2(UserService userService) {
        this.userService = userService;
    }

    public void sayHi() {
        println("hi,UserController2...");
        userService.sayHi();
    }
}

:Setter注入

注意:Setter 注⼊和属性的Setter⽅法实现类似,只不过在设置set⽅法的时候需要加上@Autowired 注解

代码语言:javascript代码运行次数:0运行复制
@Controller
public class UserController {
    // 注⼊⽅法: Setter⽅法注⼊
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void sayHi() {
        println("hi,UserController...");
        userService.sayHi();
    }
}
二:三种注入方式的优缺点分析

1:属性注入的优缺点

(1)优点

简洁,使用方便

(2)缺点

①只能用于IoC容器,非IoC容器使用会报空指针异常

②不能注入一个Final修饰的属性

解释:@Autowired底层是基于反射来注入的,它需要一个无参的构造方法或setter方法来完成注入操作,final 属性必须在声明时或构造方法中初始化,不能通过 setter 或反射修改。

举例以下这段代码

代码语言:javascript代码运行次数:0运行复制
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyService {

    @Autowired
    private final SomeDependency someDependency; // 使用了 final 修饰

    public MyService() {
        // 默认构造方法
    }
}

运行会抛出以下异常——Bean对象创建异常,不能注入,嵌套异常

代码语言:javascript代码运行次数:0运行复制
Caused by: org.springframework.beans.factory.BeanCreationException: 
Could not autowire field: final SomeDependency; 
nested exception is java.lang.IllegalArgumentException: 
Can not set final field

2:构造函数注入的优缺点

(Spring4.X推荐)

(1)优点

①可以注入final修饰的属性

②注入的对象不会被修改

③依赖对象在使用前一定会被完全初始化

④通用性好,构造方法是JDK支持的,所以更换其它任何框架,都是适用的

举例注入final修饰的属性

代码语言:javascript代码运行次数:0运行复制
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyService {

    private final SomeDependency someDependency; // 使用 final 修饰

    // 构造函数注入
    @Autowired
    public MyService(SomeDependency someDependency) {
        this.someDependency = someDependency;
    }

}
(2)缺点

注入多个对象,代码会比较繁琐

:Setter方法注入的优缺点

(1)优点

①在类实例之后,还可以重新对该对象进⾏配置或者注⼊

(2)缺点

①不能注入一个Final修饰的属性

②如果setter方法被多次调用的话,注入对象就有被修改的风险

总结:三种注入依赖的方式中,构造方式最为推荐,但是现实开发中,我们程序员基本首选都是@Autowired哈哈,你猜为啥~~~

三:类中Bean有多个时,指定默认Bean

【Spring】方法注解@Bean,配置类扫描路径-CSD博客

在这篇文章中,我们对于一个类中存在多个Bean对象时,提出的解决方式是,根据名称获取Bean对象,(名称默认是方法名)如果名称太拐杖,我们还可以进行重命名。但是这种方式明显比较复杂,下面我们介绍三种解决方式

0:引入问题代码供参考

代码语言:javascript代码运行次数:0运行复制
@Component
public class BeanConfig {
    @Bean("u1")
    public User user1() {
        User user = new User();
        user.setame("zhangsan");
        user.setAge(18);
        return user;
    }

    @Bean
    public User user2() {
        User user = new User();
        user.setame("lisi");
        user.setAge(19);
        return user;
    }
}
代码语言:javascript代码运行次数:0运行复制
@Controller
public class UserController {
    @Autowired
    private UserService userService;
    // 注⼊user
    @Autowired
    private User user;

    public void sayHi() {
        println("hi,UserController...");
        userService.sayHi();
        println(user);
    }
}

1:@Primary

使⽤@Primary注解:当存在多个相同类型的Bean注⼊时,加上@Primary注解,来确定默认的实现

代码语言:javascript代码运行次数:0运行复制
@Component
public class BeanConfig {
    @Primary // 指定该bean为默认bean的实现
    @Bean("u1")
    public User user1() {
        User user = new User();
        user.setame("zhangsan");
        user.setAge(18);
        return user;
    }
}

2:@Qualifier

指定当前要注入的Bean对象,在这个注解的value属性中,指定要注入的Bean的名称

注意:@Qualifier不能单独使用,必须搭配@Autowired使用

代码语言:javascript代码运行次数:0运行复制
@Controller
public class UserController {
    @Qualifier("user2") // 指定bean名称
    @Autowired
    private User user;

    public void sayHi() {
        println("hi,UserController...");
        println(user);
    }
}

:@Resource

这个注解是JDK提供的,对@Resource中name属性进行赋值,指定Bean的名称进行注入,

代码语言:javascript代码运行次数:0运行复制
@Controller
public class UserController {
    @Resource(name = "user2")
    private User user;

    public void sayHi() {
        println("hi,UserController...");
        println(user);
    }
}
四:@Autowired和@Resource有什么区别

1:@Autowired是Spring框架提供的注解,@Resource是JDK提供的注解

2:@Autowired默认是按照类型注入,而@Resource是按照名称注入,可以支持更多的参数设置,比如name ,type。例如以下这段代码

这也是面试常考的一个点

代码语言:javascript代码运行次数:0运行复制
import javax.annotation.Resource;
import org.springframework.stereotype.Component;

@Component
public class MyService {

    @Resource(name = "specificDependency", type = )
    private SomeDependency someDependency;

    public void performTask() {
        ();
    }
}

@Component("specificDependency")
class SomeDependency {
    public void execute() {
        println("Dependency executed!");
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2025-01-06,如有侵权请联系 cloudcommunity@tencent 删除依赖注入注解spring对象异常

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1184098.html

相关标签:无
上传时间: 2025-07-22 07:09:38
留言与评论(共有 18 条评论)
本站网友 快速美白的办法
8分钟前 发表
代码语言:javascript代码运行次数:0运行复制@Controller public class UserController { @Resource(name = "user2") private User user; public void sayHi() { println("hi
本站网友 张舒媛
22分钟前 发表
之前我们学习了@Autowired这个注解
本站网友 租车报价
18分钟前 发表
args); // 从Spring上下⽂中获取对象 UserController userController = (UserController) context.getBean("userController"); // 使⽤对象 userController.sayHi(); } } 运行结果2:构造方法注入注意:如果类只有⼀个构造⽅法
本站网友 百度贴吧助手版
7分钟前 发表
你猜为啥~~~三:类中Bean有多个时
本站网友 水鱼吃什么
23分钟前 发表
配置类扫描路径-CSD博客在这篇文章中
本站网友 云计算呼叫中心
16分钟前 发表
Spring提供了三种依赖注入的方式1:属性注入属性注⼊是使⽤ @Autowired 实现的
本站网友 手机壁纸论坛
15分钟前 发表
根据名称获取Bean对象
本站网友 毛巾
1分钟前 发表
我们程序员基本首选都是@Autowired哈哈
本站网友 抢滩
1分钟前 发表
指定默认Bean【Spring】方法注解@Bean
本站网友 国家电力投资集团
13分钟前 发表
所以更换其它任何框架
本站网友 福州妇科医院
27分钟前 发表
也就是使用Bean对象一:DI详解依赖注入是一个过程
本站网友 美女胸大图片
19分钟前 发表
@Resource是JDK提供的注解2:@Autowired默认是按照类型注入
本站网友 瘦身霜
15分钟前 发表
(名称默认是方法名)如果名称太拐杖
本站网友 许永昌
8分钟前 发表
你猜为啥~~~三:类中Bean有多个时
本站网友 恩迪亚耶
30分钟前 发表
下面我们介绍三种解决方式0:引入问题代码供参考代码语言:javascript代码运行次数:0运行复制@Component public class BeanConfig { @Bean("u1") public User user1() { User user = new User(); user.setame("zhangsan"); user.setAge(18); return user; } @Bean public User user2() { User user = new User(); user.setame("lisi"); user.setAge(19); return user; } }代码语言:javascript代码运行次数:0运行复制@Controller public class UserController { @Autowired private UserService userService; // 注⼊user @Autowired private User user; public void sayHi() { println("hi
本站网友 凌雄租赁
15分钟前 发表
指定要注入的Bean的名称注意:@Qualifier不能单独使用
本站网友 铝行业
20分钟前 发表
之前我们学习了@Autowired这个注解