2.2、基于注解的DI注入
学习资源:动力节点的2020最新Spring框架教程【IDEA版】-Spring框架从入门到精通
基于注解的 DI,是指通过 Spring 提供的注解完成容器对象的创建、属性初始化,而不再需要使用配置文件声明创建 bean 了。
注解使用步骤:
- 导入 maven 依赖 spring-context
- 在实体类加入注解
- 在 spring 配置文件中,配置组件扫描器,用于指定扫描哪些包下的注解
Spring 常用注解:
- @Component
- @Respotory
- @Service
- @Controller
- @scope
- @Value
- @Autowire
- @Resource
0、准备工作
0.1、导入 maven 依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
0.2、创建实体类
0.3、配置组件扫描器
组件扫描器的工作方式:spring 会扫描逼历 base-package 指定的包及子包中所有的类,找到类中的注解,按照注解的功能创建对象或给属性赋值。
配置组件扫描器,在配置文件中加入:
<context:component-scan base-package="com.chen.pojo"/>
指定扫描多个包的方式:
- 使用多次组件扫描器,扫描不同的包
<context:component-scan base-package="com.chen.pojo"/>
<context:component-scan base-package="com.chen.domain"/>
......
- 使用分隔符 ; 或 , 分割多个包
<context:component-scan base-package="com.chen.pojo;com.chen.domain;......"/>
- 指定父包
<context:component-scan base-package="com.chen"/>
1、@Component
作用等同于配置文件中的 <bean> ,用于向容器中创建对象。需要在实体类上使用注解 @Component
,该注解的 value 属性用于指定该 bean 的 id 值,id 自定义唯一,value 属性可缺省。
使用实例:
- @Component(value="自定义名称")
@Component(value="student")
public class Student{
}
- @Component("自定义名称"),推荐使用
@Component(value="student")
public class Student{
}
- @Component(),此时 bean 会使用 spring 提供的默认名称:类名首字母小写
@Component()
public class Student{
}
另外, Spring 还提供了 3 个创建对象的注解:
- @Repository:用于对持久层类(DAO 实现类)进行注解
- @Service:用于对业务层类(Service 实现类)进行注解
- @Controller:用于对控制器类(Controller 实现类)进行注解
这三个注解与 @Component 都可以创建对象,但这三个注解还有其他的含义:@Repository 创建持久层对象,持久层对象是可以操作数据库的;@Service 创建业务层对象,业务层对象可以加入事务功能;@Controller 注解创建的对象可以作为处理器接收用户的请求。
@Repository、@Service、@Controller 是用于给项目的对象分层的:持久层、业务层、控制层。而当你不确定某一个对象的角色时,可以使用 @Component 。
2、@Value
功能等同于 <\property name="" value="">
,用于给简单类型的属性赋值。
需要在属性上使用注解@Value,该注解的 value 属性用于指定要注入的值。使用该注解完成属性注入时,类中无需 setter。当然,若属性有 setter,则也可将其加到 setter 上。
使用实例:
- 在属性定义的上面使用,无需 setter ,推荐使用
@Componnet("student")
public class Student{
// @Value(value = "张san"),value属性可不写
@Value("张san")
private String name;
@Value("29")
private int age;
}
- 在 setter 上使用
@Componnet("student")
public class Student{
private String name;
private int age;
@Value("张三")
public void setName(String name) {
this.name = name;
}
@Value("29")
public void setAge(String age) {
this.age = age;
}
}
3、@Scope
功能同 <\bean> 的scop 属性相同,在实体类上使用,用于设置 bean 的作用域。
- @Scope("singleton"):单例
- @Scope("prototype"):多例
4、@Atuowired(不推荐使用了)
功能与 <bean ... autowire="">
相同,用于为引用类型的属性赋值。@Atuowired 默认使用的是 byType 自动从容器中装配 Bean。
4.1、byType
byType 是 @Atuowired 的默认方式,直接在属性上使用,类中无需 setter。若属性有 setter,也可将其加到 setter 上。推荐直接在属性上使用。
使用实例:
@Component("student")
public class Student {
@Value("16")
private int age;
@Autowired
private School school;
}
///////////////////////////////////////////////////////////////////////
@Component("school")
public class School {
@Value("3000")
private int area;
}
4.2、byName
需要再借助另一个注解 @Qualifier("容器中 bean 的 id"),才可以更改 @Atuowired 的自动装配方式。
@Autowirted
@Qualifier(value="容器中bean的id")
使用实例:
@Component("student")
public class Student {
@Value("16")
private int age;
@Autowired
@Qualifier("stuSchool")
private School school;
}
///////////////////////////////////////////////////////////////////////
@Component("stuSchool")
public class School {
@Value("3000")
private int area;
}
3.3、required
required 是 @Autowired 的一个属性,默认值为 true。建议使用 true
- true 表示如果引用类型赋值失败,程序报错终止执行
- false 表示如果引用类型赋值失败,程序正常执行,引用类型赋为 null、
@Component("student")
public class Student {
@Value("16")
private int age;
@Autowired(required=true)
private School school;
}
4、@Resource
@Resource 是 JDK 的注解,Spring 提供了对它的支持。
同 @Atuowired 一样,@Resource 也是既可以 byType,也可以 byName,默认是 byName。
@Resource 可用在属性上,也可以用在 setter 上,推荐直接用在属性上。
4.1、byType
@Resource 注解若不带任何参数, 采用默认 byName 的方式注入,若 byName 失败,则转而使用 byType。
使用实例:
@Component("student")
public class Student {
@Value("16")
private int age;
@Resource
private School school;
}
///////////////////////////////////////////////////////////////////////
@Component("stuSchool")
public class School {
@Value("3000")
private int area;
}
4.2、byName
@Resource 注解指定其 name 属性的值,则 name 的值即为按照名称进行匹配的 Bean 的 id。
@Component("student")
public class Student {
@Value("16")
private int age;
@Resource(name="stuSchool")
private School school;
}
///////////////////////////////////////////////////////////////////////
@Component("stuSchool")
public class School {
@Value("3000")
private int area;
}
5、注解与XML对比
注解的优点:
- 方便
- 直观
- 高效(代码少,没有配置文件的书写那么复杂)、
注解的缺点:
- 以硬编码的方式写入到 Java 代码中,修改是需要重新编译代码的
XML 方式优点是:
- 配置和代码是分离的
- 在 xml 中做修改,无需编译代码,只需重启服务器即可将新的配置加载
缺点:
- 编写麻烦,效率低,大型项目过于复杂
最佳实践:注解为主,配置文件为辅