目录
1.存储Bean对象
之前在进行存储Bean对象时需要在spring-config中添加一行bean的注册内容才可以,现在只需要添加相对应的注解就可以代替。则对应添加所需要的如下步骤:
1.1 前置工作:配置扫描路径
在spring-config.xml文件添加的配置如下:
注意:想要将对象成功存储至spring中,我们需要进行配置一下存储对象的扫描包路径,只有被配置的包下的所有类,添加了注解才能被正确识别并保存spring中。
1.2 添加注解存储Bean对象
想要将对象存储在Spring中,有两种注解可以实现:
- 类注解(区分业务功能):@Controller、@Service、@Repository、@Component、@Configuration
方法注解:@Bean
1.2.1 五大类注解
@Controller(控制器存储)效验参数的合法性
使用@Controller注解 存储的bean代码如下:
package org.java.example;
import org.springframework.stereotype.Controller;
@Controller
public class User {
public void say(){
System.out.println("hello,user!");
}
}
需要使用五大类注解,只需要在对应的类前选择自己需要的注解即可,引用方式相同。
- @Controller(控制器存储)效验参数的合法性
- @Service(服务)业务组装:
- @Repository(数据持久层)实际的业务处理
- @Component(组件)工具类层
- @Configuration(配置)配置层,针对于当前项目的设置
配置对应的扫描路径应包含所有包中的类,这样利用注解可以实现bean对象的存储。获取对象时采用名称+类型获取bean对象,对应默认的名称为类名称或将类名转化为小写都可以。也可以在对应的类注解后添加名称属性,获取bean对象。
1.2.2 Java项目标准分层
1.2.3 方法类注解
类注解是添加在某一个类上的,而方法注解是放在某个方法上的。
注意:@Bean 注解必需要配合五大类注解一起使用,才能将所要存储的bean对象存储至spring中。Spring存储bean的逻辑结构:多个名称指向一个bean对象。而五大类注解只能拥有一个名称。
@Bean获取存储对象默认名称为方法名;也可以在对应的bean注解后添加对应的名称获取对象;也可以在bean注解后添加(name = “名称”)获取对应法bean对象;也可以在bean注解后添加(value= “名称”)获取对应法bean对象,在@Bean注解中支持重命名扩展,可以在注解中使用多个名称。
注意:在获取bean对象时,如果在bean注解后已经设置对应的属性名称,此时在利用方法名获取bean对象时不可行的,因此只能使用bean注解后设置的名称用来获取bean对象。如果bean注解后未设置名称可以利用方法名获取bean对象。
在设置名称属性后利用方法名访问:
设置属性名后利用属性名访问:
@Bean名称注意事项:
如果多个bean使用相同的名称,那么指向程序不会报错,但是第一个bean之后的对象不会被存储到IoC容器中,也就是只有在第一次创建bean的时候会将对象和bean的名称关联起来,后续再有相同名称的bean存储的时候,容器会自动忽略。
2. 获取对象
获取bean对象也叫作对象装配,就是将对象取出来放到某个类中,同时也叫对象注入。
对象装配的实现方式有三种:
- 属性注入
- 构造方法注入
- Setter注入
2.1 属性注入
属性注入是指使用@Autowired实现的,将service类注入到Controller中。
依赖注入和依赖查找的区别:
依赖查找是要依赖Bean对象的名称,无论是在五大类注解还是在对应的bean注解中都需要依照存储的bean对象名称进行查询。
依赖注入是利用@Autowired注解,首先根据getType(从容器中)获取对象,如果只获取一个,那么直接将此对象注入到当前属性上;如果获取到多个对象,才会使用getName进行匹配。
当依赖注入出现多个同类型对象,在获取bean对象时出现不能分辨为该类型下的哪一个对象时,出现错误如下:
同种类型的不同名称的进行获取出现冲突的解决方案:
- 将属性的名称和bean对象的名称对应上:
package org.example.demo.service;
import org.example.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class UserService2 {
@Autowired
private User user1;
public void say(){
System.out.println("hi,user" + user1.toString());
}
}
2.利用@Autowired和@Qualifier注解配合使用,@Qualifier注解+对应类型的名称明确该类型的名称。
package org.example.demo.service;
import org.example.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class UserService2 {
//确认该类型的不同名称
@Qualifier("user2")
@Autowired
private User user;
public void say(){
System.out.println("hi,user" + user.toString());
}
}
属性注入的优缺点:
优点:实现简单、使用简单。利用@Autowired注解就可以在不new对象的情况下,直接获得注入的对象。
缺点:(1)功能向问题:无法注入final修饰的变量。被final修饰的变量直接进行赋值,后边不可以被修改或者在构造方法中给final修饰的变量赋值。
(2)通用性问题:只能适用于IoC容器。可能会写多个元素之间的依赖,违反单一原则.
(3)设计性问题:更容易违背单一设计原则。
2.2 Setter注入
同样利用@Autowired注解,添加至对应的 Setter方法之前,获取bean对象。
Setter注入的优缺点:
优点: 符合单一职责的设计原则,每一个 Setter只针对一个对象。
缺点:(1)不能注入不可变对象(final修饰的变量)
(2)注入的对象可以被修改。 Setter方法存在多次被调用的可能,因此注入的对象存在被修改的风险。
2.3 构造方法注入 (Spring 4.x)
在Spring 4.X之后主流的属性注入方法为构造方法注入,在对应该属性构造方法之前加上@Autowired注解(也可以不加,默认存在),实现bean对象的获取。
注意:@Autowired注解在当前类中只存在一个构造方法则可以省略。如果存在多个,则@Autowired注解不可以省略。
使用构造方法注入的优点和缺点:
优点:(1)可注入不可变对象(final修饰的变量)
(2)注入的对象不会被修改。构造方法在执行时只执行一次,不存在多次执行,因此对象不会存在被修改的风险。
(3)注入的对象完全被初始化。构造方法是最先被执行的。
(4)通用性更好
缺点:(1)写法比属性注入复杂。
(2)没有办法解决循环依赖的问题
2.4 @Resource:另一种注入的注解
在进行类注入的时候,除了可以使用@Autowired关键字,还可以使用@Resource进行注入。
在一些情况下使用@Autowired注解可能会出现报错信息,但是对于运行不会造成影响,对于这类情况在执行@Autowired注解下的信息之前所执行的内容是查询不到的(对于mapper层编译的内容),但是对于程序确是真实存在的,使用@Resource就不会出现上述情况。
@Resource和@Autowired的区别
- 出身不同:@Autowired来自于Spring,而@Resource来源于JDK注解
- 使用时设置的参数不同:相比于@Autowired来说只支持一个参数设置(required),而@Resource支持更多的参数设置,例如:根据设置的name获取bean对象
- 使用上的区别:@Autowired可用于Setter注入、构造函数注入和属性注入,而@Resource只能用于Setter注入和属性注入,不能用于构造函数注入。