欢迎关注个人主页:逸狼
创造不易,可以点点赞吗
如有错误,欢迎指出~
依赖注⼊是⼀个过程,是指IoC容器在创建Bean时,去提供运⾏时所依赖的资源,⽽资源指的就是对象. 在上⾯程序案例中,我们使⽤了 @Autowired 这个注解,完成了依赖注⼊的操作. 简单来说,就是把对象取出来放到某个类的属性中.
注入方式
关于依赖注⼊,Spring也给我们提供了三种⽅式:
1. 属性注⼊(FieldInjection)
2. 构造⽅法注⼊(ConstructorInjection)
3. Setter注⼊(SetterInjection)
属性注⼊
属性注⼊是使⽤@Autowired 实现的,将Service类注⼊到Controller类中. Service类的实现代码如下:
@Service
public class UserService {
public void sayHi(){
System.out.println("hi,UserService..." );
}
}
@Controller // 将对象存储到 Spring 中
public class UserController {
@Autowired
private UserService service;
public void sayHi(){
System.out.println("hi,UserController...");
service.sayHi();
}
}
构造⽅法注⼊
构造⽅法注⼊是在类的构造⽅法中实现注⼊,如下代码所⽰:
@Controller // 将对象存储到 Spring 中
public class UserController {
private UserService service;
@Autowired
public UserController(UserService userService){
this.service = userService;
}
public void sayHi(){
System.out.println("hi,UserController...");
service.sayHi();
}
}
注意事项:如果类只有⼀个构造⽅法,那么@Autowired注解可以省略;如果类中有多个构造⽅法, 那么需要添加上@Autowired来明确指定到底使⽤哪个构造⽅法。
Setter注⼊
Setter注⼊和属性的Setter⽅法实现类似,只不过在设置set⽅法的时候需要加上@Autowired注 解,如下代码所⽰:
@Controller // 将对象存储到 Spring 中
public class UserController {
private UserService service;
@Autowired
public void setService(UserService userService){
this.service = userService;
}
public void sayHi(){
System.out.println("hi,UserController...");
service.sayHi();
}
}
三种注⼊优缺点分析
- 属性注⼊ ◦
- 优点: 简洁,使⽤⽅便;
- 缺点:
- 只能⽤于IoC容器,如果是⾮IoC容器不可⽤,并且只有在使⽤的时候才会出现NPE(空指 针异常)
- 不能注⼊⼀个Final修饰的属性
- 构造函数注⼊(Spring4.X推荐)
- 优点:
- 可以注⼊final修饰的属性
- 注⼊的对象不会被修改
- 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法 是在类加载阶段就会执⾏的⽅法.
- 通⽤性好,构造⽅法是JDK⽀持的,所以更换任何框架,他都是适⽤的
- 缺点: 注⼊多个对象时,代码会⽐较繁琐
- 优点:
- Setter注⼊(Spring3.X推荐)
- 优点:⽅便在类实例之后,重新对该对象进⾏配置或者注⼊
- 缺点:
- 不能注⼊⼀个Final修饰的属性
- 注⼊对象可能会被改变,因为setter⽅法可能会被多次调⽤,就有被修改的⻛险.
@Autowired存在问题
当同⼀类型存在多个bean时,使⽤@Autowired会存在问题
@Component//@Bean要配合类注解使用
public class BeanConfig {
@Bean
public User user1(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
user.setGender("男");
return user;
}
@Bean
public User user2(){
User user = new User();
user.setName("lisi");
user.setAge(81);
user.setGender("女");
return user;
}
}
@Controller // 将对象存储到 Spring 中
public class UserController {
//注⼊user
@Autowired
private User user;
public void sayHi(){
System.out.println("hi,UserController...");
System.out.println(user);
}
}
报错的原因是,⾮唯⼀的Bean对象。
解决方案
Spring提供了以下⼏种解决⽅案:
- @Primary :当存在多个相同类型的Bean注⼊时,加上@Primary注解,来确定默认的实现.
- @Qualifier : 指定当前要注⼊的bean对象。在@Qualifier的value属性中,指定注⼊的bean 的名称。@Qualifier注解不能单独使⽤,必须配合@Autowired使⽤
- @Resource: 按照bean的名称进⾏注⼊。通过name属性指定要注⼊的bean的名称
代码示例
@Primary
@Component
public class BeanConfig {
@Primary
@Bean
public User user1(){
...
}
@Bean
public User user2(){
...
}
}
@Qualifier
@Controller
public class UserController {
//注⼊user
@Autowired
@Qualifier("user2")
private User user;
public void sayHi(){
System.out.println("hi,UserController...");
System.out.println(user);
}
}
@Resource
@Controller
public class UserController {
//注⼊user
@Resource(name = "user2")
private User user;
public void sayHi(){
System.out.println("hi,UserController...");
System.out.println(user);
}
}
常⻅⾯试题:@Autowird与@Resource的区别
- @Autowired是spring框架提供的注解,⽽@Resource是JDK提供的注解
- @Autowired默认是按照类型注⼊,⽽@Resource是按照名称注⼊.相⽐于@Autowired来说, @Resource⽀持更多的参数设置,例如name设置,根据名称获取Bean.