目录
1.什么是DI?
依赖注⼊是⼀个过程,是指IoC容器在创建Bean时, 去提供运⾏时所依赖的资源,⽽资源指的就是对象
简单来说, 就是把对象取出来放到某个类的属性中.
关于依赖注⼊, Spring也给我们提供了三种⽅式:
1.属性注⼊(Field Injection)
2.构造⽅法注⼊(Constructor Injection)
3.Setter 注⼊(Setter Injection)
都是使用@Autowired实现的。
接下来,我们分别来看.
2.依赖注入的三种⽅式
都是使用@Autowired实现的
我们接下来会频繁使用到UserService类和UserController类以及获取 UserController 中的 sayHi⽅法。
1.UserService代码:
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void doService(){
System.out.println("doService~~~~");
}
}
2.UserController类依照我们选择的注入⽅式决定。
3.获取 UserController 中的 sayHi⽅法:
import com.wh.ioc.Controller.UserController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
//@ComponentScan(basePackages = "~~~~~")
@SpringBootApplication
public class SpringIocApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringIocApplication.class, args);
UserController bean = context.getBean(UserController.class);
bean.sayHi();
}
}
2.1属性注⼊
UserController类的实现代码如下:
import com.wh.ioc.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
@Autowired
private UserService userService;
public void sayHi(){
userService.doService();
System.out.println("UserController Hi");
}
}
2.2构造⽅法注⼊
import com.wh.ioc.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
private UserService userService;
public UserController() {
}
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
public void sayHi(){
userService.doService();
System.out.println("UserController Hi");
}
}
注意:
如果类只有⼀个构造⽅法,那么 @Autowired 注解可以省略;如果类中有多个构造⽅法,那么需要添加上 @Autowired 来明确指定到底使⽤哪个构造⽅法。
补充:
关于构造函数规范:
1.当我们添加有参构造函数时,一定也要把无参构造函数也添加上。
2.依赖注入时,就算只有一个构造函数也要添加@Autowired注解
2.3Setter 注⼊
注解一定不能少
import com.wh.ioc.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
public void sayHi(){
userService.doService();
System.out.println("UserController Hi");
}
}
2.4三种注⼊优缺点分析
1.属性注⼊
优点:
简洁,使⽤⽅便
缺点:
(1) 只能⽤于 IoC 容器 ,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指 针异常)(2) 不能注⼊⼀个Final修饰的属性
2.构造函数注⼊(Spring 4.X推荐)
优点:
(1)注⼊的对象不会被修改
(2)可以注⼊final修饰的属性
(3)依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法 是在类加载阶段就会执⾏的⽅法
(4)通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的
缺点:
注⼊多个对象时, 代码会⽐较繁琐
3.Setter注⼊(Spring 3.X推荐)
⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
缺点:
1.不能注⼊⼀个Final修饰的属性
2.注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险
3.@Autowired存在问题
我们接下来用打印学生信息的例子来说明
Student类:
import lombok.Data;
@Data
public class Student {
private String name;
private Integer id;
public Student() {
}
public Student(String name) {
this.name = name;
}
public Student(String name, Integer id) {
this.name = name;
this.id = id;
}
}
BeanConfig类:
import com.wh.ioc.Model.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfig {
@Bean
public Student StudentInfo() {
return new Student("wh",01);
}
@Bean
public Student StudentInfo2() {
return new Student("Bob",02);
}
}
DomeController类:
import com.wh.ioc.Model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class DomeController {
@Autowired
private Student student;
public void say(){
System.out.println(student);
}
}
启动类:
import com.wh.ioc.Controller.DomeController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
//@ComponentScan(basePackages = "~~~~~")
@SpringBootApplication
public class SpringIocApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringIocApplication.class, args);
DomeController bean = context.getBean(DomeController.class);
bean.say();
}
}
运行:
报错的原因是,⾮唯⼀的 Bean 对象
解释:
@Autowired是先按照类型去注入,匹配到多个对象时,再按照名称去注入。
如果我们明确注入对象的名称,则可以正确打印该学生信息。
DomeController类代码:
import com.wh.ioc.Model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class DomeController {
@Autowired
private Student StudentInfo2;
public void say(){
System.out.println(StudentInfo2);
}
}
结果:
那当我们没有明确注入对象的名称,又想得到正确结果我们可以怎么做?
1.@Primary2.@Qualifier3.@Resource
1. @Primary
使⽤@Primary注解:当存在多个相同类型的Bean注⼊时,加上@Primary注解,来确定默认的实现。
直接加到Bean注⼊的方法上。
@Primary @Bean public Student StudentInfo() { return new Student("wh", 01); }
2.@Qualifier
@Controller public class DomeController { @Qualifier("StudentInfo2") @Autowired private Student student; public void say(){ System.out.println(student); } }
3.@Resource注解
本身就是依赖注入注解,是按照bean的名称进⾏注⼊。
@Controller public class DomeController { @Resource(name = "StudentInfo") private Student student; public void say(){ System.out.println(student); } }
那@Autowird 与 @Resource的区别是?
1.@Autowired 是spring框架提供的注解,⽽@Resource是JDK提供的注解
2.@Autowired 默认是按照类型注⼊,⽽@Resource是按照名称注⼊. 相⽐于 @Autowired 来说, @Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean
以上为我个人的小分享,如有问题,欢迎讨论!!!
都看到这了,不如关注一下,给个免费的赞