怎样才能比之前更简单的 读取和存储对象 (Bean) 呢?
答: 就两个字"使用注解", 接下来就说说如何利用注解来更简单的操作 Bean
目录
一. 前置工作 (配置扫描路径)
二. 使用注解存储 Bean
2.1 注解介绍
2.1.1 类注解存储 Bean 的默认命名规则
2.2 @Controller (控制器存储)
2.3 @Service (服务存储)
2.4 @Repository (仓库存储)
2.5 @Component (组件存储)
2.6 @Configuration (配置存储)
2.7 为甚使用这么多的类注解?
2.8 方法注解 Bean
2.8.1 重命名 Bean
三. 更简单的获取 Bean 对象
3.1 属性注入
3.2 Setter 注入
3.3 构造方法注入
面试题 :
一. 依赖注入和依赖查找的区别
二. 同类型的 Bean 存储到容器多个, 获取时报错问题
三. @Autowired 和 @Resource 的区别
一. 前置工作 (配置扫描路径)
为什么我们要配置存储对象的扫描包路径 ?
答: 因为只有被配置的包下的所有类, 添加了注解才能被正确的识别并保存(存储)到 Spring 中;
开始配置
在 Spring-config.xml 添加如下配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:content="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 只有当前目录下的类,才会扫描是否添加了注解,如果添加了注解, 就将这些加了注解的类存到 Spring(Ioc) 容器中-->
<!-- 使用注解存储 bean 和使用 XML 存储 bean 是一样的-->
<content:component-scan base-package="com.java.demo">
</content:component-scan>
</beans>
如果添加了注解, 没有配置扫描包路径, 他是不会被存储到 Spring 中的, 所以这点很重要
这样就配置完成了, 接下来看看如何使用注解存储 Bean
二. 使用注解存储 Bean
2.1 注解介绍
两种注解类型可以实现 :
1, 类注解 :
@Controller 控制器 : 检验参数的合法性 (安检系统)
@Service 服务 : 业务组装 (客服中心)
@Repository 数据持久层 : 实际业务处理 (实际办理的业务)
@Component 组件 : 工具类层 (基础的工具)
@Configuration 配置层 : 配置
类注解之间的关系 : @Component 是其他四个注解的父类
2, 方法注解 :
@Bean
2.1.1 类注解存储 Bean 的默认命名规则
- 第一种: 首字母大写
获取方式: 首字母名小写就可以获取到对象
User user = context.getBean("user", User.class);
- 第二种 : 首字母和第二个字母都是大写
获取方式: 使用原类名就可以
UConfig uConfig = context.getBean("UConfig",UConfig.class);
总结 :
类名如果不满足首字母是大写, 第二个字母是小写的规则时, 使用原类名就可以了
如果满足首字母大写, 第二个字母小写的情况, 首字母小写就可以了
jdk 命名规则:
2.2 @Controller (控制器存储)
核心代码:
package com.java.demo.controller;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
public void sayHi() {
System.out.println("Hi, UserController");
}
}
添加了注解之后就可以直接获取到 Bean
2.3 @Service (服务存储)
核心代码:
package com.java.demo.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void sayHi() {
System.out.println("Hi, UserService");
}
}
2.4 @Repository (仓库存储)
package com.java.demo;
import org.springframework.stereotype.Repository;
@Repository
public class User {
public void sayHi() {
System.out.println("Hi, User~");
}
}
2.5 @Component (组件存储)
package com.java.demo;
import org.springframework.stereotype.Component;
@Component
public class Student {
public void sayHi() {
System.out.println("Hi, Student~");
}
}
2.6 @Configuration (配置存储)
package com.java.demo;
import org.springframework.context.annotation.Configuration;
@Configuration
public class APPConfig {
public void sayHi() {
System.out.println("Hi APPConfig");
}
}
2.7 为甚使用这么多的类注解?
这些注解的功能都是一样的, 但是所代表的东西是不一样的
例如 : 学校要求各个班的班长一起开会, 然后我们所有班长就去了, 虽然我们的职责是一样的但是我们的所代表的班级是不一样的, 院长看见我他就知道我是 软件工程班的,如果他想了解软件工程班的情况, 就会直接问我得到确切的消息
他们之间的调用流程:
2.8 方法注解 Bean
方法注解是配合类注解一起使用的, 如果单纯的使用 @Bean 会报错
如果不对 Bean 进行重命名, 他的默认命名就是 方法名
2.8.1 重命名 Bean
1.
@Bean(" ") //设置单个名称
2.
@Bean(nane = " ") //设置单个名称
@Bean(nane = {" ", " "}) //可以设置多个名称, 此时 name 可以省略
3.
@Bean(value = " ") //设置单个名称
@Bean(value = {" ", " "}) //可以设置多个名称
4.
@Bean ({" "," "}) //可以设置多个名称
1, 直接加双引号进行重命名就可以
获取的是实体类对象
2, 使用 name 标签设置多个名字
3, 使用 value 对 Bean 设置多个名称
name 和 value 也可以省略直接写 {"", ""}
三. 更简单的获取 Bean 对象
获取 Bean 对象 : 对象装配, 把对象取出来放到某个类中, 也叫做对象注入
有三种方式 :
属性注入
构造方法注入
Setter 注入
3.1 属性注入
使用 @Autowired 注入
优点 : 使用简单
缺点 :
1 无法注入 final 修饰的变量
2 通用性问题 : 只适用于 Ioc 容器
3 更容易违背单一设计原理, 因为使用起来比较简单
使用注解 @Autowired 把 UserRepository 注入到 UserService 中
3.2 Setter 注入
优点 : 通常 Setter 只 set 一个属性, 所以 Setter 注入更符合单一设计原理
缺点 :
1 无法注入一个 final 修饰变量
2 setter 注入的对象可以被修改, setter 本来就是一个方法,既然是一个方法就有可能被多次调用和修改
3.3 构造方法注入
优点 :
1 可以注入一个 final 修饰的变量
2 注入对象不会被修改, 因为构造方法只会加载一次
3 构造方法注入可以保证注入对象完全初始化
4 构造方法的通用性更好
缺点 :
1 写法比属性注入复杂
2 使用构造方法注入, 无法解决循环依赖的问题
面试题 :
一. 依赖注入和依赖查找的区别
- 依赖查找依赖的是 Bean 名称
- @Autowired 依赖注入的流程 : 首先先根据 getType (从容器中) 获取对象, 如果只获取一个, 那么直接将此对象注入到当前属性上; 如果获取到多个对象, 才会使用 getName (根据名称) 进行匹配
二. 同类型的 Bean 存储到容器多个, 获取时报错问题
解决方案 :
1 将属性的名字和 Bean 的名称对应写上
2 使用 @Autowired 配合 @Qualifier(" ") 使用
三. @Autowired 和 @Resource 的区别
1 . 出身不同 : @Resource 来自于 JDK ; @Autowired 来自于 Spring 框架
2 . 支持参数不同 : @Resource 支持很多参数设置; @Autowired 只支持一个参数设置
3 . 使用上的区别 : @Resource 不支持构造方法注入; @Autowired 支持构造方法注入
4 . idea 兼容性支持不同, 使用 @Autowired 在 idea 专业版下可能会误报; @Resource 不存在误报的问题