目录
IoC & DI
IOC(控制反转)详解
依赖注入的三种方式
IoC & DI
IoC: Inversion of Control (控制反转), 也就是说 Spring 是⼀个"控制反转"的容器.
控制反转:也就是控制权反转. 什么的控制权发⽣了反转? 获得依赖对象的过程被反转了
也就是说, 当需要某个对象时, 传统开发模式中需要⾃⼰通过 new 创建对象, 现在不需要再进⾏创
建, 把创建对象的任务交给容器, 程序中只需要依赖注⼊ (Dependency Injection,DI)就可以了.
这个容器称为:IoC容器. Spring是⼀个IoC容器, 所以有时Spring 也称为Spring 容器。
DI: Dependency Injection(依赖注⼊)
容器在运⾏期间, 动态的为应⽤程序提供运⾏时所依赖的资源,称之为依赖注⼊。
依赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,就是指通过
引⼊ IoC 容器,利⽤依赖关系注⼊的⽅式,实现对象之间的解耦。
IOC(控制反转)详解
共有两类注解类型可以实现Bean的存储:
1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration.
2. ⽅法注解:@Bean.
类注解
1、@Controller(控制器存储)
使⽤ @Controller 存储 bean 的代码如下所⽰:
@Controller // 将对象存储到 Spring 中
public class UserController {
public void sayHi(){
System.out.println("hi,UserController...");
}
}
表示将这个类的对象存储到ioc容器当中,并表明这是一个controller类。负责 接收请求, 对请求进⾏处理, 并进⾏响应。
2、@Service(服务存储)
使⽤ @Service 存储 bean 的代码如下所⽰:
@Service
public class UserService {
public void sayHi(String name) {
System.out.println("Hi," + name);
}
}
表示将这个类的对象存储到ioc容器当中,并表明这是一个service类。负责处理具体的业务逻辑。
3、@Repository(仓库存储)
使⽤ @Repository 存储 bean 的代码如下所⽰:
@Repository
public class UserRepository {
public void sayHi() {
System.out.println("Hi, UserRepository~");
}
}
表示数据访问层,也称为持久层. 负责数据访问操作。
4、@Component(组件存储)
使⽤ @Component 存储 bean 的代码如下所⽰:
@Component
public class UserComponent {
public void sayHi() {
System.out.println("Hi, UserComponent~");
}
}
单纯将这个类的对象加入到ioc容器中,没有其他含义。
5、@Configuration(配置存储)
使⽤ @Configuration 存储 bean 的代码如下所⽰:
@Configuration
public class UserConfiguration {
public void sayHi() {
System.out.println("Hi,UserConfiguration~");
}
}
表示配置层. 处理项⽬中的⼀些配置信息。
方法注解
@Bean
@Bean注解可以将类中的方法注入到ioc容器当中,使一个类可以拥有多个对象。
使用@Bean注解存储bean代码如下:
@Component
public class BeanConfig {
@Bean
public User user(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
}
注:@Bean注解必须搭配@Component注解使用才能生效。否则无效。
@Bean注解的优势在于同一个类可以定义多个对象:
@Component
public class BeanConfig {
@Bean
public User user1(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
@Bean
public User user2(){
User user = new User();
user.setName("lisi");
user.setAge(19);
return user;
}
}
类中的两个Bean对象的名称如下:
可以通过设置 name 属性给 Bean 对象进⾏重命名操作,如下代码所⽰:
@Bean(name = {"u1","user1"})
public User user1(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
依赖注入的三种方式
关于依赖注⼊, Spring给我们提供了三种⽅式:
1. 属性注⼊(Field Injection)
属性注⼊是使⽤ @Autowired 实现的,如将 Service 类注⼊到 Controller 类中.
Service 类的实现代码如下:
@Service
public class UserService {
public void sayHi() {
System.out.println("Hi,UserService");
}
}
Controller 类的实现代码如下:
@Controller
public class UserController {
//注⼊⽅法1: 属性注⼊
@Autowired
private UserService userService;
public void sayHi(){
System.out.println("hi,UserController...");
userService.sayHi();
}
}
最终结果如下:
2. 构造方法注⼊(Constructor Injection)
构造⽅法注⼊是在类的构造⽅法中实现注⼊,如下代码所示:
@Controller
public class UserController2 {
//注⼊⽅法2: 构造⽅法
private UserService userService;
@Autowired
public UserController2(UserService userService) {
this.userService = userService;
}
public void sayHi(){
System.out.println("hi,UserController2...");
userService.sayHi();
}
}
注意事项:如果类只有⼀个构造⽅法,那么 @Autowired 注解可以省略;如果类中有多个构造⽅法,那么需要添加上 @Autowired 来明确指定到底使⽤哪个构造⽅法。
3. Setter 注⼊(Setter Injection)
Setter 注⼊和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired 注
解 ,如下代码所⽰:
@Controller
public class UserController3 {
//注⼊⽅法3: Setter⽅法注⼊
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
public void sayHi(){
System.out.println("hi,UserController3...");
userService.sayHi();
}
}
特殊情况:当同一类型存在多个bean对象时,使用@Autowired会出现问题。
@Component
public class BeanConfig {
@Bean("u1")
public User user1(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
@Bean
public User user2() {
User user = new User();
user.setName("lisi");
user.setAge(19);
return user;
}
}
@Controller
public class UserController {
@Autowired
private UserService userService;
//注⼊user
@Autowired
private User user;
public void sayHi(){
System.out.println("hi,UserController...");
userService.sayHi();
System.out.println(user);
}
}
spring提供了以下解决方案:
@Primary
使⽤@Primary注解:当存在多个相同类型的Bean注⼊时,加上@Primary注解,来确定默认的实现.
@Component
public class BeanConfig {
@Primary //指定该bean为默认bean的实现
@Bean("u1")
public User user1(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
@Bean
public User user2() {
User user = new User();
user.setName("lisi");
user.setAge(19);
return user;
}
}
@Qualifier
使⽤@Qualifier注解:指定当前要注⼊的bean对象。 在@Qualifier的value属性中,指定注⼊的bean的名称。
• @Qualifier注解不能单独使⽤,必须配合@Autowired使⽤
@Controller
public class UserController {
@Qualifier("user2") //指定bean名称
@Autowired
private User user;
public void sayHi(){
System.out.println("hi,UserController...");
System.out.println(user);
}
}
@Resource
使⽤@Resource注解:是按照bean的名称进⾏注⼊。通过name属性指定要注⼊的bean的名称。
@Controller
public class UserController {
@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。
以上关于IOC与DI,希望对你有所帮助。