• Spring的使用2.0


    目录

    Spring的创建和使用 

    创建Spring项目 

    存储Bean对象

    类注解

    方法注解

    获取Bean对象(对象注入) 

    属性注入 

    Setter注入 

    构造方法注入 

    @Resource 

    @ Autowired和@Resource的区别

    同一个类型多个Bean报错的问题 

    使用@Resource(name="指定Bean的名称")

    使用@Autowired+@Qualifier(value = "") 


    前面的博客中已经介绍了Spring的创建和使用第一版,第一版现在已经不怎么在使用了。下面将介绍目前Spring的常见用法。

    Spring中想要更简单的存储和读取对象的核心方法是使用注解。 

    Spring的创建和使用 

    1.先创建出Spring项目出来

    2.存储Bean对象

    3.获取Bean对象 

    创建Spring项目 

    和1.0一样创建出一个Spring项目出来并在pom.xml文件中添加核心jar包,以及创建一个启动类:

    存储Bean对象

    在resources目录下面配置Spring.xml文件,Spring.xml文件中需要配置Spring组件的扫描路径:

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:content="http://www.springframework.org/schema/context"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd
    7. http://www.springframework.org/schema/context
    8. https://www.springframework.org/schema/context/spring-context.xsd">
    9. //下面是配置文件的扫描路径,根据自己的文件所在的位置来处理这个路径
    10. <content:component-scan base-package="com.user">content:component-scan>
    11. beans>

    上面是配置文件的扫描路径,根据自己的文件所在的位置来处理这个路径,像我在com.user.Controller目录下面创建了一个控制层文件UserController,那么我的扫描路径就可以写成com.user,这样设置以后Spring在扫描文件的时候,他就会去该目录下面查看。这里的写法不是唯一的,你也可以将路径写大一点,比如直接com也可以,但是不推荐。

    给存储Bean对象添加注解 

    想要将对象存储在Spring中,就得给对象添加注解,二注解又分两种:类注解、方法注解 

    类注解

    顾名思义就是在类的前面加上注解,像下面这样:

    1. @Controller
    2. public class UserController {
    3. public void Hi(String name){
    4. System.out.println("Hi:"+name);
    5. }
    6. }

    类注解包括:@Controller(控制器存储)、@Service(服务存储)、@Repository(仓库存储)、@Component(组件存储)、@Configuration(配置存储)

    首先我们的明白,我们再写一个Spring项目的时候,因为涉及到前后端的交互还有和数据库的交互。各个目录之间的层级关系一定要明确,关于层级关系,它相当于是编程规范,实行这种规范可以方便开发和维护代码,具体的东西还请自己去了解。 

    Controller处在控制层,主要负责前端数据的校验 ;

    Service处在服务层,主要负责数据的处理还有组装;

    Repository处在存储层,主要负责数据库中表的操作,以及将数据存储在数据库中;

    Configuration处在配置层,主要负责管理系统的配置信息;

    Component处在组件层,主要负责存放编写Spring项目所需要的公共组件。

    它们之间的关系如下图:

    其中 

    @Controller(控制器存储)、@Service(服务存储)、@Repository(仓库存储)、@Configuration(配置存储)都是@Component(组件存储)的子类

    方法注解

    在方法的上面加上注解,方法注解必须配合类注解才能一起使用(因为Spring在扫描的时候是以类为单位来扫描的,如果类上面不加上注解,就扫描不到) :

    1. @Controller
    2. public class UserController {
    3. @Bean
    4. public User GoodBey(){
    5. User user = new User();
    6. user.setId(1);
    7. user.setName("韩梅梅");
    8. return user;
    9. }
    10. }
    1. public class User {
    2. private int Id;
    3. private String name;
    4. public void setId(int id) {
    5. Id = id;
    6. }
    7. public void setName(String name) {
    8. this.name = name;
    9. }
    10. @Override
    11. public String toString() {
    12. return "User{" +
    13. "Id=" + Id +
    14. ", name='" + name + '\'' +
    15. '}';
    16. }
    17. }

    现在先来看一下它们的使用:

    现在来详细讨论一下这两类注解:

    方法注解目前包括:@Bean

    在使用方法注解的时候要注意:方法注解必须配合类注解才能使用。

    在我们写方法注解的时候,有时方法名可能很长,这时可以给Bean对象进行重命名操作,但是重命名以后就不能再使用方法名:

    1. @Bean(name = "GB")
    2. public User GoodBey(){
    3. User user = new User();
    4. user.setId(1);
    5. user.setName("韩梅梅");
    6. return user;
    7. }

    关于Bean的命名 

    通常在使用注解的时候,要求在写类名的时候要采用大驼峰,而读取类名的时候要求类名的首字母要小写。如果类名中首个字母和第二个字母都是大写,那么在读取类名的时候就按照类名来读就可以了,这个时候不能在采用类名首字母小写,否者会报错:

    我们查看Spring里面的原码就知道原因了:

    在IDEA中按查找类的快捷键ctrl+N,找到AnnotationBeanNameGenerator这个类:

    然后查看这个方法:

    从上面就可以解释为什么会报错了 

    获取Bean对象(对象注入) 

    获取Bean对象也叫对象注入,是把对象取出放到某个类中。

    对象注入的实现有以下3种方式:

    1.属性注入

    2.Setter注入

    3.构造方法注入 

    属性注入 

    属性注入就是在属性上面添加@Autowired注解。将UserService类注入到UserController类中,像下面这样:

    1. @Service
    2. public class UserService {
    3. /*
    4. * 根据ID获取用户数据
    5. */
    6. public User findUserById(Integer id){
    7. User user = new User();
    8. if(id==1){
    9. user.setId(1);
    10. user.setName("张三");
    11. }else{
    12. user.setId(2);
    13. user.setName("李四");
    14. }
    15. return user;
    16. }
    17. public void Hi(String name){
    18. System.out.println("Hi:"+name);
    19. }
    20. }
    1. @Controller
    2. public class UserController {
    3. //1.属性注入,从Spring中获取一个对象,并注入到当前类
    4. @Autowired
    5. private UserService userService;
    6. public User findSuerById(Integer id){
    7. return userService.findUserById(id);
    8. }
    9. public void Hi(String name){
    10. System.out.println("Hi:"+name);
    11. }
    12. }
    1. public class App {
    2. public static void main(String[] args) {
    3. //1.获取到Spring的上下文
    4. ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
    5. //2.加载类注解Bean对象
    6. UserController userController = context.getBean("userController", UserController.class);
    7. //3.使用它里面的方法
    8. System.out.println(userController.findSuerById(1));
    9. }
    10. }

    Setter注入 

    通过获得setter方法,然后在set方法上面加上@Autowired,将UserService类注入到UserController类中,像下面这样:

    1. @Controller
    2. public class UserController2 {
    3. private UserService userService;
    4. //1.Setter注入
    5. @Autowired
    6. public void setUserService(UserService userService) {
    7. this.userService = userService;
    8. }
    9. public User findUserById(Integer id){
    10. return userService.findUserById(id);
    11. }
    12. }
    1. public class App {
    2. public static void main(String[] args) {
    3. //1.获取到Spring的上下文
    4. ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
    5. //2.加载类注解Bean对象
    6. UserController2 controller2 = context.getBean("userController2", UserController2.class);
    7. //3.使用它里面的方法
    8. System.out.println(controller2.findUserById(1));
    9. }
    10. }

    利用Setter注入方式的步骤:1.定义属性 、2.生成属性setter方法、3.给setter方法添加@Autowired注解

    构造方法注入 

    构造方法注入是在类的构造方法中注入,将UserService类注入到UserController类中,像下面这样:

    1. @Controller
    2. public class UserController3 {
    3. private UserService userService;
    4. @Autowired
    5. public UserController3(UserService userService) {
    6. this.userService = userService;
    7. }
    8. public User findUserById(Integer id){
    9. return userService.findUserById(id);
    10. }
    11. }
    1. public class App {
    2. public static void main(String[] args) {
    3. //1.获取到Spring的上下文
    4. ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
    5. //2.加载类注解Bean对象
    6. UserController3 userController3 = context.getBean("userController3", UserController3.class);
    7. //3.使用它里面的方法
    8. System.out.println(userController3.findUserById(1));
    9. }
    10. }

    注意:在使用构造方法注入的时候,如果类中只存在一个构造方法,那么可以省略这个构造方法上面的注解@Autowired,但是两个和两个以上的构造方法的时候@Autowired不能省略。 

    三种注解优缺点:

    • 属性注解的优点是简洁,使用方便;缺点是只能用于IoC容器,如果是非IoC容器用属性注入,则会报空指针异常,还有就是不能注入不可变对象(final修饰的对象);
    • Setter方式注入的优点符合单一设计原则;缺点是不能注入不可变对象(final修饰的对象)而且通用性不如构造方法;
    • 构造方法注入的优点是通用性好,在使用之前一定能保证注入的类不为空,而且可以注入不可变对象;缺点是如果有多个注入会显得比较臃肿; 

    @Resource 

    我们在使用依赖注入的时候,不光只有@Autowired一种方式,还有另一种方式@Resource

    @ Autowired和@Resource的区别

    •  它们两个出身不同,@Autowired来自于Spring,而@Resource来自于JDK的注解;
    •  @Resource注解不能使用在构造方法上,而@Autowired可以;
    • 使用时设置的参数不同,@Resource对于@Autowired来说支持更多的参数设置,比如name,利用这一点可以给类名起别名。
    1. @Component
    2. public class UserBean {
    3. @Bean(name = "GB1")
    4. public User GoodBey1(){
    5. User user = new User();
    6. user.setId(1);
    7. user.setName("韩梅梅");
    8. return user;
    9. }
    10. @Bean(name = "GB2")
    11. public User GoodBey2(){
    12. User user = new User();
    13. user.setId(2);
    14. user.setName("李华");
    15. return user;
    16. }
    17. }
    1. @Controller
    2. public class UserController4 {
    3. @Resource(name="GB1")
    4. private User user;
    5. public User findClient(){
    6. return user;
    7. }
    8. }
    1. public class App {
    2. public static void main(String[] args) {
    3. //1.获取到Spring的上下文
    4. ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
    5. //2.加载类注解Bean对象
    6. UserController4 userController4 = context.getBean("userController4", UserController4.class);
    7. //3.使用它里面的方法
    8. System.out.println(userController4.findClient());
    9. }
    10. }

    同一个类型多个Bean报错的问题 

    之前在1.0版本中,我们讨论过获取Bean的时候,对于多个对象的同一种类型的Bean获取会报错

    比如像下面这样:

    1. @Component
    2. public class UserBean {
    3. @Bean(name = "GB1")
    4. public User GoodBey1(){
    5. User user = new User();
    6. user.setId(1);
    7. user.setName("韩梅梅");
    8. return user;
    9. }
    10. @Bean(name = "GB2")
    11. public User GoodBey2(){
    12. User user = new User();
    13. user.setId(2);
    14. user.setName("李华");
    15. return user;
    16. }
    17. }
    1. @Controller
    2. public class UserController5 {
    3. @Autowired
    4. private User user;
    5. public User findClient(){
    6. return user;
    7. }
    8. }
    1. import com.user.Controller.*;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. public class App {
    5. public static void main(String[] args) {
    6. //1.获取到Spring的上下文
    7. ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
    8. //2.加载类注解Bean对象
    9. UserController5 userController5 = context.getBean("userController5", UserController5.class);
    10. //3.使用它里面的方法
    11. System.out.println(userController5.findClient());
    12. }
    13. }

    在分析出现上述错误之前,我们的先明白一个事情,那就是@Autowired和@Resource两个注解获取Bean对象是通过两种方式来获取的:

    1.通过类型来获取 

    context.getBean(UserController5.class)

    2.通过名称来获取

    context.getBean("userController5")

    如果根据名称来获取,获取不到,那么这两个注解就会去根据类型来获取,如果都获取不到就会报错。

    现在再来分析上面报错的原因,在UserBean类里面,有两个方法,这两个方法的类型都是User,其中一个方法名是GB1,另一个是GB2。而我们在UserController5类里面将User类通过属性注入的方式注入进来,但是我们取Bean的名称为user,@Autowired就会在com.user目录下面去找这个Bean对象,很明显是找不到的。然后@Autowired就会采用类型User的方式来找,在UserBean类里面他发现有两个User类型的Bean对象,这是它就不知道调用那一个了,所以就会报错。 

    通过上面的分析,我们就可以在UserController5类里面修改Bean的名称,比如改为GB1:

    1. @Controller
    2. public class UserController5 {
    3. @Autowired
    4. private User GB1;
    5. public User findClient(){
    6. return GB1;
    7. }
    8. }

    但是如果现在不能修改Bean对象的名称,那就通过一下的方法来解决了:

    使用@Resource(name="指定Bean的名称")

    这种方式在介绍@Resource就演示过了,所以不在演示。

    使用@Autowired+@Qualifier(value = "") 

    1. @Controller
    2. public class UserController5 {
    3. @Autowired
    4. @Qualifier(value = "GB1")
    5. private User user;
    6. public User findClient(){
    7. return user;
    8. }
    9. }

  • 相关阅读:
    人工网络英语怎么说,人工网络英语怎么写
    【idea】win 10 / win 11:idea 、Alibaba Dragonwell 11、maven、git 下载与安装
    linux精通 4.1
    电脑清理c盘怎么清理全教程,教你彻底清理所有垃圾
    【Linux kernel/cpufreq】framework ----big Little driver
    【rtp-benchmarks】读取本地文件基于uvgRtp实现多线程发送
    《银行法律法规》三、银行管理——5、风险管理
    数据库第三次作业
    CocosCreator3.8研究笔记(十八)CocosCreator UI组件(二)
    携职教育:2022年初级会计成绩查询倒计时,这几件事一定要注意
  • 原文地址:https://blog.csdn.net/yahid/article/details/126568656